.NET

Serialisation – JSON in C#, using Json.NET

Last week we compared a number of different data-interchange formats and I explained why my current favourite is JSON.

JSON’s syntax is very simple. So easy in fact, that it can be expressed on a single page.

This makes it easy to remember and write. Further, it makes writing a JSON parser very easy as well.

However, there already are many solutions for all major, and many smaller languages and environments.

header

So instead of reinventing the wheel, today I would like to give an introduction to Json.NET, the library I have been using to read and write JSON for about two years now.

I will take a very practical approach, giving an overview over the basic features. Further, I will highlight some of the additional features of the library that I have found useful in the past, and we will extend the library to allow for parsing of custom non-trivial types.

Json.NET basics

The basic usage of Json.Net is very simple.

The static class JsonConvert has a number of methods to serialise to and deserialise from JSON.

It does so by using reflection to do all the heavy lifting for us, and no additional code on our side is needed.

The library is very flexible however, and most of its behaviour can be extended or overridden as needed.

We will use the following class from last week (albeit slightly simplified) to show basic serialisation and deserialisation.

class UnitTemplate
{
    public string Name { get; set; }
    public float Speed { get; set; }
    public float Health { get; set; }
    public List<string> Weapons { get; set; }
}

Serialisation

To serialise an object using Json.NET, we can simply pass it to JsonConvert.SerialiseObject() Doing so with the object created as follows:

var template = new UnitTemplate
{
    Name = "Tank",
    Speed = 0.5f,
    Health = 100,
    Weapons = new List<string>
        { "big cannon", "small turret" }
};

yields this result:

{"Name":"Tank","Speed":0.5,"Health":100.0,"Weapons":["big cannon","small turret"]}

By default Json.NET will use no white space to improve the size of the output. However, by passing Formatting.Indented to the above method’s formatting parameter, we can easily get the following output.

{
  "Name": "Tank",
  "Speed": 0.5,
  "Health": 100.0,
  "Weapons": [
    "big cannon",
    "small turret"
  ]
}

This is much more readable, and I would prefer this in almost all cases unless the size is a definite problem.

Note that this method works great for pretty much any type, including dictionaries and other collections. It also works great with anonymous types, allowing easy dumping of arbitrary data to a file in a structured way without having to create container types that are not used for anything else.

Apart from its additional parameters, we can also modify this method’s behaviour in a number of different ways. One of them is by using attributes, to control how our data is serialised.

They can be found in the official documentation, but there is one I have found particularly useful:

JsonIgnoreAttribute

This attribute is an easy way to prevent Json.NET from serialising properties that do not have to be. This is particularly useful if a type contains a property which does not have any backing data on its own, but infers its value from other properties.

Imagine for example a rectangle type with properties Width, Height and Area. The area would neither have to be stored in memory, nor in JSON, but could always be calculated on the fly when needed.

By simply placing [JsonIgnore] in front of our Area property, Json.NET will ignore it when serialising.

Deserialisation

Deserialisation with Json.NET is almost equally simple to serialisation.

We can simply use the generic method JsonConvert.DeserializeObject<T>().

There also is a non-generic overload, but if we know the type of data we are expecting – which should be the case most of the time – using the generic version will give us type-safety and relieves us from having to do additional parsing.

Without giving an example, it suffices to say that parsing either of the JSON from above results in a new object identical to the one we had before.

Serialiser settings and converters

Json.Net’s static serialisation and deserialisation method’s also take additional parameters.

One of them is the JsonSerializerSettings, which can be used to control the process in a variety of ways.

If you are looking into using Json.NET for more than minor things, I encourage you to take a look at the type’s documentation`.

Alternatively, the static methods take a list of JsonConverters.

These converters are in essence the meat of the Json.NET library, determining how different values and types are written and read.

The library comes with several implementations that can be quite useful. My personal favourite is StringEnumConverter, which reads and writes enum values as their string names, instead of as numbers, greatly improving readability.

Custom converters – extending Json.NET

In additional to the provided converters, we can also write our own by extending JsonConverter.

Take for example the following converter, which serialises System.Color into a hexadecimal string, and back.

class ColorConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var c = (Color)value;
        var rgbInt = c.A << 24 | c.R << 16 | c.G << 8 | c.B;
        var hexString = string.Format("#{0:X8}", rgbInt);
        writer.WriteValue(hexString);
    }
 
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var hexString = (string)reader.Value;
        var rgbInt = int.Parse(hexString.Substring(1), NumberStyles.HexNumber);
        return Color.FromArgb(rgbInt);
    }
 
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Color);
    }
}

Note that Json.NET already serialises Color without any problems. The example merely serves to show how easy it is to create custom converters.

JsonSerializer

One last useful feature of Json.NET I will mention here is the JsonSerializer class.

This class can be used to keep both the state from JsonSerializerSettings as well as a list of converters. As a result, one only has to configure it once and can then use it as many times as needed.

Conclusion

In this post, I gave a short introduction into the basics of serialising and deserialising JSON in C#, using Json.NET. I hope this has been useful, and please let me know if you have any questions. Also make sure to leave a comment if you would like me to go further into this or any other topic.

Enjoy the pixels!

Reference: Serialisation – JSON in C#, using Json.NET from our NCG partner Paul Scharf at the GameDev<T> blog.

Paul Scharf

Paul is a self-publishing game developer. He believes that C# will play an ever growing role in the future of his industry. Next to working on a variety of projects he writes weekly technical blog posts on C#, graphics, and game development in general.

Related Articles

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button