danielwertheim

danielwertheim


notes from a passionate developer

Share


Sections


Tags


Disclaimer

This is a personal blog. The opinions expressed here represent my own and not those of my employer, nor current or previous. All content is published "as is", without warranty of any kind and I don't take any responsibility and can't be liable for any claims, damages or other liabilities that might be caused by the content.

Not only rainbows and hug bears with JSON.Net camel case

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

View Comments