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