The CamelCaseContractResolver
in Newtonsoft JSON.Net, as of today, is not only rainbows and hug bears. How-ever, things seems to be changing with this pull request: https://github.com/JamesNK/Newtonsoft.Json/pull/922; which is highly welcomed. Why? Because as of today, with no hooked in custom conventions or formatters, there's one BIG CAVEAT. It can mess up the "dynamic" experience. Let me explain.
I've experienced this with MyCouch as well as when authoring internal messagebus solutions used in distributed system. Using the camel case convention is no big deal until someone decides to put something dynamic in there. Like a simple Dictionary<string, string>
. Then you really need to take control of the conventions around the KEY. If you add something with the key being "MySweetKey"
that will be serialized as "mySweetKey"
. What would then happen if someone at the receiving end tries to access it as "MySweetKey"
after deserialized it back to the Dictionary
?
Correcto! Your logs will contain an entry with: "KeyNotFoundException"
.
Sample
Instead of producing a KeyNotFoundException
this sample will use ContainsKey
instead.
public class Foo
{
public Dictionary<string, string> Attrs { get; set; }
}
var settingsDefault = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
};
var settingsCamel = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var fooOrg = new Foo
{
Attrs = new Dictionary<string, string>
{
{"MySweetKey", "Some value"}
}
};
var jsonDefault = JsonConvert.SerializeObject(fooOrg, settingsDefault);
var jsonCamel = JsonConvert.SerializeObject(fooOrg, settingsCamel);
var fooFromDefault = JsonConvert.DeserializeObject<Foo>(jsonDefault);
var fooFromCamel = JsonConvert.DeserializeObject<Foo>(jsonCamel);
WriteLine("===== ===== =====");
WriteLine("DEFAULT");
WriteLine(jsonDefault);
WriteLine(fooFromDefault.Attrs.ContainsKey("MySweetKey"));
WriteLine("===== ===== =====");
WriteLine("CAMEL");
WriteLine(jsonCamel);
WriteLine(fooFromCamel.Attrs.ContainsKey("MySweetKey"));
WriteLine("===== ===== =====");
Outputs:
===== ===== =====
DEFAULT
{"Attrs":{"MySweetKey":"Some value"}}
True
===== ===== =====
CAMEL
{"attrs":{"mySweetKey":"Some value"}}
False
===== ===== =====
DEFAULT FROM CAMEL
True
So not only sunshine, rainbows and hug bears with the CamelCaseContractResolver
. But yes, I do understand that the convention is more popular especially exposed from an API. But please note. As it is right now, it can give you unwanted behaviour. I can for sure say I look forward to getting this stuff with naming strategies and options to tell it how-to handle Dictionaries. Then it will be rainbows and hug bears.
//Daniel