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 DictionaryToDictionaryListConverter<TKey, TValue> : JsonConverter
class DictionaryDTO : Dictionary<TKey, TValue>
public DictionaryDTO(KeyValuePair<TKey, TValue> pair) : base(1) { Add(pair.Key, pair.Value); }
public override bool CanConvert(Type objectType)
return typeof(IDictionary<TKey, TValue>).IsAssignableFrom(objectType) && objectType != typeof(DictionaryDTO);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
var token = JToken.Load(reader);
var dict = (IDictionary<TKey, TValue>)(existingValue as IDictionary<TKey, TValue> ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
if (token.Type == JTokenType.Array)
foreach (var item in token)
using (var subReader = item.CreateReader())
serializer.Populate(subReader, dict);
else if (token.Type == JTokenType.Object)
using (var subReader = token.CreateReader())
serializer.Populate(subReader, dict);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
var dict = (IDictionary<TKey, TValue>)value;
serializer.Serialize(writer, dict.Select(p => new DictionaryDTO(p)));
public Dictionary<string, string> Value { get; set; }
[JsonConverter(typeof(DictionaryToDictionaryListConverter<string, string>))]
public Dictionary<string, string> Value { get; set; }
public MyDictionary Value { get; set; }
[JsonConverter(typeof(DictionaryToDictionaryListConverter<string, string>))]
public class MyDictionary : Dictionary<string, string>
public class AddressValueConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(AddressValue);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
var addressValue = (existingValue as AddressValue ?? new AddressValue());
var token = JObject.Load(reader);
var property = token.Properties().SingleOrDefault();
addressValue.Label = property.Name;
addressValue.Value = (string)property.Value;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
var addressValue = (AddressValue)value;
serializer.Serialize(writer, new Dictionary<string, string> { { addressValue.Label, addressValue.Value } });
[JsonConverter(typeof(AddressValueConverter))]
public class AddressValue
public string Label { get; set; }
public string Value { get; set; }
public class RootObjectAddressValue
public List<AddressValue> Value { get; set; }
public static string GetJson()
var json = @"{""value"":[
{""street"":""Karlova 25""},
{""gpsLat"":""50.1571""},
public static void Test()
Test<RootObject0>(new DictionaryToDictionaryListConverter<string, string>());
Test<RootObjectAddressValue>();
Console.WriteLine("Done.");
public static void Test<T>(params JsonConverter [] converters)
var settings = new JsonSerializerSettings
var root = JsonConvert.DeserializeObject<T>(json1, settings);
var json2 = JsonConvert.SerializeObject(root, Formatting.Indented, settings);
Console.WriteLine("\nReserialized {0}", root);
Console.WriteLine(json2);
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(json1), JToken.Parse(json2)));
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];