Serializing JObject to camelCase

Serializing JObject to camelCase

How to serialize a JSON.NET JObject to camelCase

Yesterday one of my colleagues (@harsimran_hs) pinged me about some weird behavior he was seeing when serializing some JSON to return from one of our APIs. The strange thing was that sometimes the results were camelCased and sometimes they were coming back PascalCased for the same method.

Some investigation uncovered that in one code path, the object being serialized was a regular C# class from our domain model and in those cases it was being correctly serialized as camelCase. But in the other code path, the object was coming in as a JObject (docs) due to some (intentional) generic code handling. In the cases where the object was a JObject, the JSON output was being PascalCased.

We initially thought it would be an easy fix and tried setting the JsonConvert.DefaultSettings (docs) to force the serializer to use camelCasing. When that didn't work, we tried moving closer to the source and providing a custom JsonSerializer at the point where the object was being serialized. When that didn't work either, we started wondering what was really going on.

As it turns out, it is by-design that JObject serialization ignores contract resolvers. So any JObject will serialize its properties as-is. That means that if you end up with a JObject that already has PascalCased properties, there is no built-in way to handle this case.

We went searching for an answer and came across a blog post from Andrew Lock that offered up a few options. The first two solutions involved avoiding even ending up with a wrongly-cased JObject in the first place, which wouldn't work in our situation. In his final solution, he suggested essentially looping over the JObject properties and manually converting them to camelCase before serializing. While this approach does work, it involved a bunch of extension methods and more code than we wanted for what was essentially a hack (Andrew called it 'hacky' himself).

So in the quest to make the hack as painless as possible, we went back to the drawing board and came up with the following one liner. Be warned, it is not the nicest line of code you are ever going to see:

myJObj = JObject.FromObject(myJObj.ToObject<ExpandoObject>(), JsonSerializer.Create(new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }));

Let's break down what it is doing:

myJObj.ToObject<ExpandoObject>() first converts the JObject into a regular object - we use ExpandoObject in this case to take advantage of its dynamic nature to support the unknown list of properties.

Then JObject.FromObject() converts the ExpandoObject back into a JObject, but this time we can apply the JsonSerializerSettings and they will be honored. The end result is a new JObject with all of the properties pre-serialized as camelCase.

Let's take this example:

And then view the resulting output, including the desired output, what we get by default, and with our new hacky-one-line solution applied (note that it even handles nested objects):

So in the end we still ended up with a hacky solution but it is all on one line now with a nice big comment explaining why we are up to these shenanigans.

If you have any better ideas, head on over to my Twitter and let me know!