JSON Extensions

Sometimes when I create a NUGET package it’s because I’ve written code to isolate my architecture from some 3rd party component that I’m using today, but, may want to move away from at some later point. My CG.Json NUGET package is a case in point. It contains a collection of extension methods that are intended to hide some of the details behind converting things to and from JSON. I originally wrote these methods before NewtonSoft had a really great JSON parser out there and I’ve just continued to use them ever since (although I do now use the NewtonSoft library internally).

I know what you’re thinking. Why create a library to perform conversions to and from JSON when the NewtonSoft library already does that, right? Well, for me it’s because I have a great deal of code already written that relies on these extension methods. If I were to stop using them now then I’d have multiple approaches to serialization going on and that would be a little confusing. Also, if I went back and pulled out calls to my extension methods and swapped them with direct calls to the NewtonSoft library then I’d have a good bit of work to get through with no real benefit in return.

So what about anyone else who hasn’t already used these methods for years? What’s the benefit for them? Well, in my mind, my library is like a design seam between some piece of architecture and the NewtonSoft library. Like any good design seam, it protects against changes. So, if there’s any likelihood that you’ll one day move away from NewtonSoft then using my library might make sense. After all, you could easily rewrite the relatively simple implementation of my extension methods and those changes would then be isolated to the CG.Json library, as opposed to having multiple changes spread out across your architecture. So if you’re sure, I mean super sure … I mean super duper sure that you won’t ever need to move away from NewtonSoft, then forget using my CG.Json package. There’s no other real benefit.

If, after everything you’ve just read, you’re still interested in at least looking at my extension methods, then let’s go do that now. :o)

CG.Json has a single public class named ObjectExtensions that contains a number of public extension methods. Here is a simplified look at the code:

If you look at the actual library code, on GITHUB, you’ll notice that ObjectExtensions class also contains methods to convert to and from XML, as well as JSON. I left the XML methods out of the listings for this article but they are still part of library.

So there are two kinds of methods: ToJson and FromJson. ToJson serializes objects to JSON and FromJSON deserializes JSON into object references. Thanks to the robustness of the NewtonSoft library, the methods are now just wrappers around the JsonConvert class, which comes from the NewtonSoft library. Back when these methods contains my gruesome attempts at JSON parsing there was more to them. We’ll speak no more of that code … :o)

Things do get a little more interesting for two reasons. (1), I need to support private setters on model properties, and (2) I need to support alternative constructors for deseralization. Now, to be sure, the NewtonSoft library already supports both of those things but I need them to be implemented in such a way that they don’t create a reference back to the NewtonSoft library because part of the reason for my library is to prevent direct references to the NewtonSoft library …

So, using the mechanisms already built into NewtonSoft, I created another, internal class, called PrivateContractResolver, and tied it into the NewtonSoft serialization settings by assigning an instance of it to the ContractResolver property of the JsonSerializerSettings object, as you can see In the FromJson code listing. That one extra line of code directs NewtonSoft to call on my private resolver when performing the deserialization. This way, I can control the deserialization in wild and exciting ways. Let’s look at the simplified code for the PrivateContractResolver class now:

As shown in the listing, the PrivateContractResolver class is derived from the DefaultContractResolver class. That means we get all the default NewtonSoft JSON behavior from scratch, unless we make changes to those defaults. For us, to support private property setters and alternative constructors, that means overriding the CreateProperty and CreateObjectContract methods.

Let’s start with the CreateProperty method. We begin by allowing the base class to create a default JsonProperty reference for us. Then, if that property doesn’t contain a public writer, we try to cast the object to a PropertyInfo reference. If the member isn’t a property that cast will fail and we’ll simply return. On the other hand, if the member is a property then the cast will succeed and we’ll use the new reference to look for a property setter. If we find one, all we have to do is set the Writable property, on the original member, to true. Once we do that, NewtonSoft will try to use the setter when it wouldn’t have otherwise.

The next step, which is the alternative constructors, is handled through our CreateObjectContract override. This method begins by allowing the base class to create a default contract resolver. Then, we use some reflection to look for a constructor, on whatever type is getting deserialized, that’s decorated with an attribute named JsonConstructor. If it finds such a constructor that means we should use it to create the object, instead of the default constructor. To get to that point we have to specify two things: (1) a delegate that NewtonSoft should use to invoke the constructor, and (2) a parameter value for each one of the parameters on that constructor. The remainder of the code in the CreateObjectContract method does exactly that.

One thing to point out though is, our JsonConstructor attribute is NOT the same one from the NewtonSoft library. That’s because, if we used the NewtonSoft version, it would require a direct reference to the NewtonSoft library in whatever code used that alternative constructor mechanism, and again, we’re trying to prevent causing anything to directly reference NewtonSoft in order to convert to or from JSON.

Here’s the code for our JsonConstructor attribute class:

Nothing special, really. Just a custom attribute for our code to find at runtime.

So how do we use these methods? Well, here are a few examples from the associated QA test fixture:

The ToJsonReturnsAJsonString method verifies that the ToJson method serializes an object

and returns a valid JSON string. Nothing special here, serializing a public class with public properties.

Here’s another example:

The FromJsonReturnsAnObject method verifies that the FromJson method deserializes an object from a valid JSON string.

Let’s look at dealing with a private setter on a property:

The FromJsonHandlesPrivateProps method verifies that the FromJson method deserializes an object

with a private property setter, from a valid JSON string.

Let’s look at dealing with an alternative constructor now:

The FromJsonWithAttr method verifies that the FromJson method knows about the JsonConstructor attribute and uses it to determine the appropriate constructor to use for deserialization.

 

That’s about it. The library is a simple, thin wrapper around the ubiquitous NewtonSoft library conversion code. Using it allows for enjoying fast, stable JSON parsing and conversion behavior without tying your project directly to the NewtonSoft NUGET package.

Have fun!

 

The code for this article is taken from my CG.Json NUGET package, which can both be downloaded for free at: https://github.com/CodeGator/CG.Json

The source code for the CG.Json project lives on Github and can be obtained for free at:

https://www.nuget.org/packages/CG.Json

 

 

Photo by hermaion from Pexels