CSharp · Console
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
ChildDictionary dict = new ChildDictionary();
dict.Name = "Roster";
dict.Add(new Employee { Id = 22, Name = "Joe", HireDate = new DateTime(2012, 4, 17) }, 1923.07);
dict.Add(new Employee { Id = 45, Name = "Fred", HireDate = new DateTime(2010, 8, 22) }, 1415.25);
string json = JsonConvert.SerializeObject(dict, Formatting.Indented);
Console.WriteLine(json);
dict = JsonConvert.DeserializeObject<ChildDictionary>(json);
Console.WriteLine("Name: " + dict.Name);
foreach (var kvp in dict)
{
Console.WriteLine("Employee Id: " + kvp.Key.Id);
Console.WriteLine("Employee Name: " + kvp.Key.Name);
Console.WriteLine("Employee Hire Date: " + kvp.Key.HireDate);
Console.WriteLine("Amount: " + kvp.Value);
Console.WriteLine();
}
}
}
[JsonConverter(typeof(ComplexDictionaryConverter<Employee, double>))]
public class ChildDictionary : Dictionary<Employee, double>
{
public string Name { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}
public class ComplexDictionaryConverter<K,V> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<K,V>)));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject obj = new JObject();
foreach (PropertyInfo prop in GetReadWriteProperties(value.GetType()))
{
object val = prop.GetValue(value);
obj.Add(prop.Name, val != null ? JToken.FromObject(val, serializer) : new JValue(val));
}
JArray array = new JArray();
foreach (var kvp in (IDictionary<K, V>)value)
{
JObject item = new JObject();
item.Add("Key", JToken.FromObject(kvp.Key, serializer));
item.Add("Value", kvp.Value != null ? JToken.FromObject(kvp.Value, serializer) : new JValue(kvp.Value));
array.Add(item);
}
obj.Add("KVPs", array);
obj.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
IDictionary<K, V> dict = (IDictionary<K, V>)Activator.CreateInstance(objectType);
foreach (PropertyInfo prop in GetReadWriteProperties(objectType))
{
JToken token = obj[prop.Name];
object val = token != null ? token.ToObject(prop.PropertyType, serializer) : null;
prop.SetValue(dict, val);
}
JArray array = (JArray)obj["KVPs"];
foreach (JObject kvp in array.Children<JObject>())
{
K key = kvp["Key"].ToObject<K>(serializer);
V val = kvp["Value"].ToObject<V>(serializer);
dict.Add(key, val);
}
return dict;
}
private IEnumerable<PropertyInfo> GetReadWriteProperties(Type type)
{
return type.GetProperties().Where(p => p.CanRead && p.CanWrite && !p.GetIndexParameters().Any());
}
}