Skip to content

Instantly share code, notes, and snippets.

@petermorlion
Last active November 12, 2022 16:45
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save petermorlion/c92e3af4ecf256d4b66c to your computer and use it in GitHub Desktop.
Save petermorlion/c92e3af4ecf256d4b66c to your computer and use it in GitHub Desktop.
Generic JsonConverter for JSON.NET and IDictionaries
// UPDATE!
// In Json.NET 7, a DictionaryKeyResolver was added.
// This might be able to fix the problem more elegantly.
// I haven't checked though.
public class DictionaryJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dictionary = (IDictionary)value;
writer.WriteStartArray();
foreach (var key in dictionary.Keys)
{
writer.WriteStartObject();
writer.WritePropertyName("Key");
serializer.Serialize(writer, key);
writer.WritePropertyName("Value");
serializer.Serialize(writer, dictionary[key]);
writer.WriteEndObject();
}
writer.WriteEndArray();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (!CanConvert(objectType))
throw new Exception(string.Format("This converter is not for {0}.", objectType));
var keyType = objectType.GetGenericArguments()[0];
var valueType = objectType.GetGenericArguments()[1];
var dictionaryType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
var result = (IDictionary)Activator.CreateInstance(dictionaryType);
if (reader.TokenType == JsonToken.Null)
return null;
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndArray)
{
return result;
}
if (reader.TokenType == JsonToken.StartObject)
{
AddObjectToDictionary(reader, result, serializer, keyType, valueType);
}
}
return result;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType && (objectType.GetGenericTypeDefinition() == typeof(IDictionary<,>) || objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
}
private void AddObjectToDictionary(JsonReader reader, IDictionary result, JsonSerializer serializer, Type keyType, Type valueType)
{
object key = null;
object value = null;
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndObject && key != null)
{
result.Add(key, value);
return;
}
var propertyName = reader.Value.ToString();
if (propertyName == "Key")
{
reader.Read();
key = serializer.Deserialize(reader, keyType);
}
else if (propertyName == "Value")
{
reader.Read();
value = serializer.Deserialize(reader, valueType);
}
}
}
}
@jsuwala
Copy link

jsuwala commented Jan 27, 2016

This gist saved me with JSON.Net version 8.
A quick hint on how to serialize and deserialize using this class:

var serializerSettings = new Newtonsoft.Json.JsonSerializerSettings();
serializerSettings.Converters.Add(new DictionaryJsonConverter());
var json = Newtonsoft.Json.JsonConvert.SerializeObject(complexDictionary, serializerSettings);
var ret = Newtonsoft.Json.JsonConvert.DeserializeObject<complexDictionaryType>(json,serializerSettings);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment