C# JSON string creation with a twist

I recently ran across a situation in which I had to verify that some C# code designed with the objective of taking an instance of a C# object representing a Country and converting it to equivalent JSON string notation still worked as we transitioned some custom C# code (.Net Framework 3.5 SP1) from SharePoint 2007 (Visual Studio 2008) to SharePoint 2010 (Visual Studio 2012).

The original developer had written a lengthy string.Format() statement in a method named toJson() to accomplish the conversion of an instance of type Country to an equivalent JSON string.   Each of the 18 properties of the Country.cs class was included in the string formatting.   The only thing special about the resulting JSON string was the use of a “wrapper” object named Country around the whole thing to allow subsequent javascript code to refer to the underlying properties as Country.Population, Country.AreaInSquareKilometers, etc.

We have been using JSON.Net in the project for several years now, so I was a bit surprised that so much effort had gone into using string.Format() to hand-craft the JSON string representation of an instance of type Country when it would have been much simpler to use JSON.Net’s built-in JsonConvert.SerializeObject() method to accomplish the same task.  Imagine how easy it would be to add a new property to the Country object and forget to update the string.Format() call to include it?  Probably some wasted time tracking down what might to some be considered an obscure error.

Upon closer inspection, it dawned on me that the original developer might not have known how to add the {Country: {….}} “wrapper” around the orignal string representation of an instance of type Country that JsonConvert.SerializeObject() provides.  There is also the possibility that he or she was totally unaware of the presence of JSON.Net to help accomplish the objective, but I would like to assume that the reason for choosing string.Format() was the former, not the later.

I can think of two ways to simplify the conversion to JSON string and at the same time automatically including any future new or renamed properties in the Country class.  I’ll start by describing the common changes that both alternatives utilize plus some supporting details that describe how an instance of class Country gets created.

An instance of Country is created by passing in a two-character country abbreviation to a method that performs a lookup and, if the corresponding country information is found, returns a fully populated instance of type Country.

Now for the changes needed in the code that serializes a Country instance to a JSON string.

First, the Country class needs to be decorated with JSON.Net’s special attribute that says “any property that doesn’t explicitly exclude itself will automatically be included when the call to JsonConvert.SerializeObject() occurs”:


[JsonObject(MemberSerialization.OptOut)]
public sealed class Country
{
public string AreaInSquareKilometers { get; set; }
public string Capital { get; set; }
(snip)

 

I’ll leave it as an exercise for the reader to figure out what JSON.Net attribute to decorate an individual property with in order to “opt out” of JSON string serialization.

 

For the first alternative, the lengthy/tedious/manual-labor-intensive string.Format() call within method toJson() of class Country can be reduced to the following:

public string toJson()

{

    var sbr = new StringBuilder();

    sbr.Append(“{\”Country\”: “);

    sbr.Append(JsonConvert.SerializeObject(this));

    sbr.Append(“}”);

    return sbr.ToString();

}

The pros and cons of the above alternative approach are as follows:

On the plus side, we have removed the need to synchronize changes to the Properties  of class Country with the string.Format() call and replaced it with something that will automatically pick up any new/changed properties that are not explicitly exempted from the JSON’izing process.

We have not necessarily made it 100% clear why the extra {Country: {…..} } wrapper is being added, but perhaps I’m not giving my fellow developers enough credit for being intelligent enough to figure this out for themselves.

A second alternative involves declaring a special “wrapper” class, which I will call CountryWrapper that acts as a container of an instance of the existing Country class.  Instead of serializing the Country class, we instead serialize the “country wrapper” class.

Here’s what CountryWrapper.cs looks like, including its toJson() method.

    /// <summary>

    /// A wrapper for the Country class to allow for the resulting JSON string

    /// to be “wrapped” by an outer {Country: {…} } designator.

    /// </summary>

    [JsonObject(MemberSerialization.OptOut)]

    public sealed class CountryWrapper

    {

        public Country Country { get; set; }

 

        /// <summary>

        /// Returns a JSON string representation of this class

        /// </summary>

        /// <returns></returns>

        public string toJson()

        {

            return JsonConvert.SerializeObject(this);

        }

    }

Here’s some code that provides the necessary conversion to JSON string by using what is assumed (for the sake of this example) that a valid instance of class Country already exists and we just need to “wrap” it and convert that “wrapped” country instance to a JSON string:

Country foundCountry = …details of creation omitted…

CountryWrapper wrapper = new CountryWrapper {Country = foundCountry};

string jsonCountry = wrapper.toJson();

The pros and cons of this alternative approach are:

On the plus side, there is no extra, possibly obscure logic involving StringBuilder to “wrap” the country information with the outer {Country: {….}} designator.

On the negative side, there is the overhead of having to instantiate an extra instance of an additional class, CountryWrapper.

You could also argue that the new toJson() method within the CountryWrapper class is somewhat “auto-magical” in terms of how it accomplishes the task of creating the outer {Country: {…}} “wrapper” around the imbedded Country class instance information when the call to JsonConvert.SerializeObject() is made.

And that, dear readers, is where I will leave you to make up your own mind or even suggest even better, hopefully simple ways to achieve the original objective, keeping in mind the goal of not touching the related javascript code that actually does something with the resulting JSON string representation of a Country instance.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s