Last active
November 12, 2022 16:45
-
-
Save petermorlion/c92e3af4ecf256d4b66c to your computer and use it in GitHub Desktop.
Generic JsonConverter for JSON.NET and IDictionaries
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist saved me with JSON.Net version 8.
A quick hint on how to serialize and deserialize using this class: