TL;DR Json.NET can serialize and deserialize dictionaries with simple keys like integers or strings. It can serialize, but not deserialize dictionaries with more complex keys.
Longer version: Json.NET uses ToString() to convert a dictionary key to JSON field identifier. A simple case works like this:
var dict = new Dictionary<int, string>
{
{10, "ten"},
{42, "forty two"}
};
var json = JsonConvert.SerializeObject(dict);
Console.WriteLine(json); // prints {"10":"ten","42":"forty two"}
var deserialized = JsonConvert.DeserializeObject<Dictionary<int, string>>(json); // gets your dictionary back
The dictionary value can be of any complex type: normal serialization rules apply.
var dict = new Dictionary<int, Tuple<int, string>>()
{
{10, Tuple.Create(10, "ten")},
{42, Tuple.Create(42, "forty two")},
};
Console.WriteLine();
var json = JsonConvert.SerializeObject(dict);
Console.WriteLine(json); // {"10":{"Item1":10,"Item2":"ten"},"42":{"Item1":42,"Item2":"forty two"}}
var deserialized = JsonConvert.DeserializeObject<Dictionary<int, Tuple<int, string>>>(json);
However, Json.NET uses ToString() to generate dictionary keys:
var dict = new Dictionary<Tuple<int, int>, string>
{
{ Tuple.Create(10,20), "ten-twenty" },
{ Tuple.Create(5,3), "five-three" },
};
var json = JsonConvert.SerializeObject(dict);
Console.WriteLine(json); // {"(10, 20)":"ten-twenty","(5, 3)":"five-three"}
var deserialized = JsonConvert.DeserializeObject<Dictionary<Tuple<int, int>, string>>(json); // blows up
It is even possible to trick Json.NET into generating duplicate keys (which appears to be technically valid JSON):
struct CustomKey
{
private readonly int _val;
public CustomKey(int val)
{
_val = val;
}
public override string ToString()
{
return "CustomKey";
}
public override int GetHashCode()
{
return _val.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is CustomKey)) return false;
return _val == ((CustomKey)obj)._val;
}
}
var dict = new Dictionary<CustomKey, string>
{
{new CustomKey(10), "ten"},
{new CustomKey(42), "forty two"}
};
var json = JsonConvert.SerializeObject(dict);
Console.WriteLine(json); // {"CustomKey":"ten","CustomKey":"forty two"}
var deserialized = JsonConvert.DeserializeObject<Dictionary<CustomKey, string>>(json); // blows up
Well, no one is perfect 🙂
