Skip to content

Instantly share code, notes, and snippets.

@NullEntity
Created July 16, 2017 01:49
Show Gist options
  • Save NullEntity/2f305076d81e6c1592b853f9b2a060ca to your computer and use it in GitHub Desktop.
Save NullEntity/2f305076d81e6c1592b853f9b2a060ca to your computer and use it in GitHub Desktop.
Saves a dictionary as key/value pairs. Importantly, it uses JsonConverters on the dictionary keys which the default JsonSerializer doesn't do.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class CustomDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(IDictionary).IsAssignableFrom(objectType) ||
TypeImplementsGenericInterface(objectType, typeof(IDictionary<,>));
}
private static bool TypeImplementsGenericInterface(Type concreteType, Type interfaceType)
{
return concreteType.GetInterfaces()
.Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == interfaceType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var dictionaryTypeArguments = objectType.GetGenericArguments();
var keyValuePairType = typeof(KeyValuePair<,>).MakeGenericType(dictionaryTypeArguments[0], dictionaryTypeArguments[1]);
var keyValuePairKeyPropertyInfo = keyValuePairType.GetProperty("Key");
var keyValuePairValuePropertyInfo = keyValuePairType.GetProperty("Value");
var keyValuePairListType = typeof(IList<>).MakeGenericType(keyValuePairType);
var keyValuePairList = (IEnumerable) serializer.Deserialize(reader, keyValuePairListType);
var dictionaryType =
typeof(Dictionary<,>).MakeGenericType(dictionaryTypeArguments[0], dictionaryTypeArguments[1]);
var dictionaryAddMethodInfo = dictionaryType.GetMethod("Add", new []{ dictionaryTypeArguments[0], dictionaryTypeArguments[1] });
var dictionary = Activator.CreateInstance(dictionaryType);
foreach (var pair in keyValuePairList)
{
var key = keyValuePairKeyPropertyInfo.GetValue(pair, null);
var value = keyValuePairValuePropertyInfo.GetValue(pair, null);
dictionaryAddMethodInfo.Invoke(dictionary, new [] { key, value });
}
return dictionary;
}
// write the dictionary as key/value pairs
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var type = value.GetType();
var keys = (IEnumerable) type.GetProperty("Keys").GetValue(value, null);
var values = (IEnumerable) type.GetProperty("Values").GetValue(value, null);
var valueEnumerator = values.GetEnumerator();
writer.WriteStartArray();
foreach (var key in keys)
{
valueEnumerator.MoveNext();
writer.WriteStartObject();
writer.WritePropertyName("key");
serializer.Serialize(writer, key);
writer.WritePropertyName("value");
serializer.Serialize(writer, valueEnumerator.Current);
writer.WriteEndObject();
}
writer.WriteEndArray();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment