I'm trying to serialize/deserialize a dictionary, the problem is that I create the dictionary with a StringComparer.OrdinalIgnoreCase
comparer.
Here is a code snippet of the problem I'm experiencing:
var dict = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
dict["x"] = new Dictionary<string, string>();
dict["x"]["y"] = "something";
var serialized = JsonConvert.SerializeObject(dict);
var unSerialized = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(serialized);
Console.WriteLine((dict.Comparer == unSerialized.Comparer ? "Same" : "Different"));
(.NET Fiddle - Try It)
Prints out the following on the console:
Different
Obviously the JSON serializer doesn't serialize the Comparer that I set when I create the dictionary, but the issue is that I can't set the Comparer after the fact since Dictionary<TKey, TValue>.Comparer
is read-only.
I'm sure it has to do with some custom JsonSerializerSetting
but I can't seem to figure out how to intercept the collection creation and return a dictionary with a different comparer.
It's a bit late probably, but it is possible to extend generated JSON using JsonConverter
will be a bit more complex, but more flexible. I've created a sample for the described case, it is not full
.NET Fiddle - Try It
(feel free to extend if you would decide to use it):
public class DictConverter<TValue> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JToken.ReadFrom(reader);
if (objectType == typeof(Dictionary<string, TValue>))
{
var comparer = obj.Value<string>("Comparer");
Dictionary<string, TValue> result;
if (comparer == "OrdinalIgnoreCase")
{
result = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase);
}
else
{
result = new Dictionary<string, TValue>();
}
obj["Comparer"].Parent.Remove();
serializer.Populate(obj.CreateReader(), result);
return result;
}
return obj.ToObject(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var obj = JObject.FromObject(value);
if (value is Dictionary<string, TValue>)
{
if((value as Dictionary<string, TValue>).Comparer == StringComparer.OrdinalIgnoreCase)
obj.Add("Comparer", JToken.FromObject("OrdinalIgnoreCase"));
}
obj.WriteTo(writer);
}
}
and usage
var dict = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
dict["x"] = new Dictionary<string, string>();
dict["x"]["y"] = "something";
var serialized = JsonConvert.SerializeObject(dict,
new DictConverter<Dictionary<string,string>>());
var unSerialized = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>
(serialized, new DictConverter<Dictionary<string, string>>());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With