How can I serialize/deserialize a dictionary with custom keys using Json.Net?

.net, c#, json, json.net

Solution

This should do the trick:

Serialization:

JsonConvert.SerializeObject(expected.ToArray(), Formatting.Indented, jsonSerializerSettings);

By calling `expected.ToArray()` you're serializing an array of `KeyValuePair<MyClass, object>` objects rather than the dictionary.

Deserialization:

JsonConvert.DeserializeObject<KeyValuePair<IDataKey, object>[]>(output, jsonSerializerSettings).ToDictionary(kv => kv.Key, kv => kv.Value);

Here you deserialize the array and then retrieve the dictionary with `.ToDictionary(...)` call.

I'm not sure if the output meets your expectations, but surely it passes the equality assertion.

Problem

I have the following class, that I use as a key in a dictionary: ``` public class MyClass { private readonly string _property; public MyClass(string property) { _property = property; } public string Property { get { return _property; } } public override bool Equals(object obj) { MyClass other = obj as MyClass; if (other == null) return false; return _property == other._property; } public override int GetHashCode() { return _property.GetHashCode(); } } ``` The test I am running is here: ``` [Test] public void SerializeDictionaryWithCustomKeys() { IDictionary<MyClass, object> expected = new Dictionary<MyClass, object>(); expected.Add(new MyClass("sth"), 5.2); JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; string output = JsonConvert.SerializeObject(expected, Formatting.Indented, jsonSerializerSettings); var actual = JsonConvert.DeserializeObject<IDictionary<MyClass, object>>(output, jsonSerializerSettings); CollectionAssert.AreEqual(expected, actual); } ``` The test fails, because Json.Net seems to be using the `ToString()` method on the dictionary keys, instead of serializing them properly. The resulting json from the test above is: ``` { "$type": "System.Collections.Generic.Dictionary`2[[RiskAnalytics.UnitTests.API.TestMarketContainerSerialisation+MyClass, RiskAnalytics.UnitTests],[System.Object, mscorlib]], mscorlib", "RiskAnalytics.UnitTests.API.TestMarketContainerSerialisation+MyClass": 5.2 } ``` which is clearly wrong. How can I get it to work?

Original source

Related problems