I have a class
public class MyValue
{
public String Prop1 { get; set; }
public String Prop2 { get; set; }
}
which I am both using as a type for a normal Property as well as a Dictionary key.
What I need is a way so that when this class is used as a Property, it is serialized as
{"Prop1":"foo","Prop2":"bar"}
but when it is used as a Dictionary key, it is serialized in a way that JSON.Net is able to deserialize it properly.
When adding a ToString() method to MyValue, I am able to create a text representation (non-JSON) that allows the usage as Dictionary key but unfortunately, I am not able to deserialize it afterwards. Even adding a JsonConverter for MyValue did not help because it seems to be unable to handle non-JSON as source format (and additionally, when serialized as a property, it IS json, so the converter would need to handle both somehow).
What you could do is serialize and deserialize your dictionary in a proxy
KeyValuePair<string, string>
array, like so:(Here I'm using the
DataContract
attributes, but I could just as easily have used[JsonIgnore]
and[JsonProperty("Dictionary")]
)So, to test this (and assuming that you have properly overridden
GetHashCode()
andEquals()
onMyValue
, which you need to do in order to use it as a dictionary key), I did the following:Sure enough, there was no exception deserializing the container, but there was deserializing the dictionary directly. And the following JSON was created for the container:
Is that what you want?
Update
Or, if you don't like the proxy arrays, you could apply the following
JsonConverterAttribute
to each and everyDictionary
property to get the same result:Update
As an alternative, you could seal your
MyValue
class and attach an appropriateTypeConverterAttribute
for converting from & to a string. JSON.Net will pick this up and use it both for dictionary keys and properties. This solution is simpler in that it's a global solution so you don't need to use proxy arrays or converter properties for each and every dictionary, however the JSON created for yourMyValue
properties isn't quite what you require.Thus:
Properties and dictionaries using this class can now be serialized without the use of any proxy arrays. For instance, serializing and deserializing the following:
Gives the following JSON when serialized:
(the quotes are escaped since they are embedded in the JSON, not part of the JSON.)
Late Update - creating a generic
TypeConverter
for dictionary keysIt's possible to create a generic
TypeConverter
that works for any generically specified type by using an appropriate contract resolver:Then apply it to your class as follows: