using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using DescriptionAttribute = System.ComponentModel.DescriptionAttribute;
public class DescriptionContractResolver : DefaultContractResolver
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
foreach (var property in props)
if (property.Converter == null
&& property.AttributeProvider.GetAttributes(typeof(System.ComponentModel.DescriptionAttribute), true) is {} array
&& ((System.ComponentModel.DescriptionAttribute)array[0]).Description is {} description)
property.Converter = new CommentConverter(description);
class CommentConverter : JsonConverter
public CommentConverter(string comment) => this.comment = comment ?? throw new ArgumentNullException(nameof(comment));
public override bool CanConvert(Type objectType) => throw new NotImplementedException("This converter is should only be applied directly to properties.");
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
writer.WriteComment(comment);
serializer.Serialize(writer, value);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
reader.MoveToContentAndAssert();
return serializer.Deserialize(reader, objectType);
public static partial class JsonExtensions
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None)
while (reader.TokenType == JsonToken.Comment)
public static JsonReader ReadAndAssert(this JsonReader reader)
throw new ArgumentNullException();
throw new JsonReaderException("Unexpected end of JSON stream.");
public class DescriptionConfiguration
[Description("Last name of the human")]
public string LastName { get; set; }
public DescriptionConfiguration()
private void SetDefaultValues(object obj)
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
DefaultValueAttribute attr = (DefaultValueAttribute) prop.Attributes[typeof(DefaultValueAttribute)];
prop.SetValue(obj, attr.Value);
public static void Test()
var model = new DescriptionConfiguration();
var resolver = new DescriptionContractResolver();
var settings = new JsonSerializerSettings
ContractResolver = resolver,
var json = JsonConvert.SerializeObject(model, Formatting.Indented, settings);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Namespace, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");