Json.NET does not always properly take into account the declared ValueType
in a Dictionary<KeyType,ValueType>
.
This makes serializing a Dictionary<string,object>
pretty unworkable if a value happens to be one for which DefaultContractResolver.CanConvertToString()
returns true, unless I'm missing something. Rect
is one such type in .NET 4.0. I tried this in Json.NET 4.5r11 and 5.0r2. Consider the following code:
_requestSerializerJson = new JsonSerializer();
// Even setting TypeNameHandling to All doesn't change the deserialized result
Dictionary<string, object> dictionary = new Dictionary<string, object>();
Rect a = new Rect(1, 2, 3, 4);
dictionary.Add("myrect", a);
byte[] bytes;
using (MemoryStream requestStream = new MemoryStream())
using (var streamWriter = new StreamWriter(requestStream))
using (var writer = new JsonTextWriter(streamWriter))
{
_requestSerializerJson.Serialize(writer, dictionary);
writer.Flush();
bytes = requestStream.ToArray();
}
// Serialized to: {"myrect":"1,2,3,4"}
using (MemoryStream stream = new MemoryStream(bytes, 0, bytes.Length))
using (var textReader = new StreamReader(stream))
using (var reader = new JsonTextReader(textReader))
{
var b = _requestSerializerJson.Deserialize<Dictionary<string, object>>(reader);
}
// b is a Dictionary with a single *string* value "1,2,3,4" instead of a Rect!
Am I thinking about this wrong or missing something? I just switched to Json.NET from XmlSerializer because it is incredibly more performant (especially at construction), and it was all fairly easy to transition to, but running into this issue scares me a bit.
It seems like if Json.NET is going to write something as a string because the object type returns true for CanConvertToString
(), it needs to write out a Json attribute indicating that a conversion to string occurred, so that it can be reliably "unconverted" on deserialization...
Dictionary<string, Rect>
do on the deserialize? – asawyer