I have an object tree that I'm serializing to JSON with DataContractJsonSerializer
. Dictionary<TKey, TValue>
gets serialized but I don't like the markup - the items are not rendered like this:
{key1:value, key2:value2}
but rather like an array of serialized KeyValuePair<TKey, TValue>
objects:
[{
"__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
"key":"key1",
"value":"value1"
},
{
"__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
"key":"key2",
"value":"value2"
}]
Ugly, isn't it?
So, I avoid this by wrapping the generic Dictionary in a custom object that implements ISerializable
, and I implement my custom serialization in the GetObjectData
method (and it takes just 3 lines).
Now the problem - I can't make my class derive from Dictionary<TKey, TValue>
, so I implement all logic (Add
, Clear
, etc.) in my custom class, being applied to a private Dictionary<TKey, TValue>
field. Inheritance would be preferable as I'll have all generic Dictionary functionality at my disposal when using my custom object.
The problem with inheritance is that Dictionary<TKey, TValue>
implements ISerializable
on its own, and DataContractJsonSerializer
seems to prefer this implementation even if I implement ISerializable
explicitly from my custom class, like this:
public class MyClass : Dictionary<string, object>, ISerializable
{
public override void GetObjectData(SerializationInfo info,
StreamingContext context)
}
I was actually surprised that this is possible as it allows me to implement the same interface twice without being obviously able to use explicit interface implementation - so I analyzed the situation in more detail in a blog post about multiple interface implementation
So, according to the experiments I did there, the serializer should be calling my implementation of ISerializable, no matter what type of casting is used internally -
((ISerializable)((Dictionary<,>)obj)).GetObjectData(...)
or:
((ISerializable)obj).GetObjectData(...)
but it apparently isn't happening as I see in the resulting JSON that the KeyValuePair<TKey, TValue>
serializer still being called. What might be happening that I'm missing?
Update: The answers and comments I'm getting so far are pretty much only suggesting workarounds. I noted, however, that I have a workaround that works quite well so with asking this question I have 2 objectives:
Eventually make it work with the original design - and I'm not going to change serialization logic just for that, there is a lot of code and logic dependent on it
To unserstand the mystery of why isn't the
DataContractJsonSerializer
using my serialization code - as can be seen in the blog post I referred, I have made all kinds of experiments with interface implementation and inheritance and I was confident that I'm grasping all the ins and outs of the process, so I'm troubled by failing to understand what's hapenning in this case
JavaScriptSerializer
as it serializes dictionaries how you prefer. – Gurkha