using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class ObjectDictionaryConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(Dictionary<string, object>);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var tokenType = reader.SkipComments().TokenType;
if (tokenType == JsonToken.Null)
var tempDictionary = new Dictionary<string, object>();
var old = reader.DateParseHandling;
reader.DateParseHandling = DateParseHandling.None;
serializer.Populate(reader, tempDictionary);
reader.DateParseHandling = old;
var dictionary = existingValue as IDictionary<string, object> ?? (IDictionary<string, object>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
foreach (var pair in tempDictionary)
dictionary.Add(pair.Key, pair.Value.ToObject());
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
public static partial class JsonExtensions
public static JsonReader SkipComments(this JsonReader reader)
while (reader.TokenType == JsonToken.Comment && reader.Read())
public static object ToObject(this object obj)
return ToObject(obj as JToken) ?? obj;
public static object ToObject(this JToken token)
return token.Children<JProperty>()
.ToDictionary(prop => prop.Name,
prop => ToObject(prop.Value));
var list = token.Select(t => ToObject(t)).ToList();
if (list.All(i => i is long))
return list.Cast<long>().ToArray();
else if (list.All(i => i is string))
return list.Cast<string>().ToArray();
else return list.ToArray();
return ((JValue)token).Value;
public class AttributeObject
public Dictionary<string, object> Attributes { get; set; }
public static void Test()
var simple = new AttributeObject
Attributes = new Dictionary<string, object>()
{"date string", "2018-10-17T04:00:00Z"},
var attributeObj = new AttributeObject
Attributes = new Dictionary<string, object>()
{"date string", "2018-10-17T04:00:00Z"},
{"string []", new [] { "a", "b", "c" }},
{"long []", new [] { 121L, 144L, 169L }},
{"object []", new object [] { "a", 121L, "2018-10-17T04:00:00Z" }},
private static void Test(AttributeObject attributeObj)
var settings = new JsonSerializerSettings
Converters = { new ObjectDictionaryConverter() },
var jsonString = JsonConvert.SerializeObject(attributeObj, Formatting.Indented, settings);
var deserializedObj = JsonConvert.DeserializeObject<AttributeObject>(jsonString, settings);
Assert.IsTrue(attributeObj.Attributes.Keys.SequenceEqual(deserializedObj.Attributes.Keys));
Assert.IsTrue(attributeObj.Attributes.Values.Select(o => GetTypeOrNull(o)).SequenceEqual(deserializedObj.Attributes.Values.Select(o => GetTypeOrNull(o))));
Assert.IsTrue(attributeObj.Attributes.Values.SelectMany(o => o is object[] ? (object[])o : new[] { o }).Select(o => GetTypeOrNull(o))
.SequenceEqual(deserializedObj.Attributes.Values.SelectMany(o => o is object[] ? (object[])o : new[] { o }).Select(o => GetTypeOrNull(o))));
Console.WriteLine("\nTests passed successfully for JSON: ");
Console.WriteLine(jsonString);
static Type GetTypeOrNull(object obj)
return obj == null ? null : obj.GetType();
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");