Serializing and Deserializing JSON in C#

The majority of my systems integration work requires me to work with 3rd party API’s or to create my own APIs. When creating my own, obviously I have full control over what the API call needs to be sent and what it will return and what shape its in. Pretty much all of my APIs work with XML data, its nice and easy to work with and the majority of people understand it at a glance.

More recently I was passed a set of 3rd party APIs that work with JSON (JavaScript Object Notation). For the purposes of this post, I am assuming that you know what JSON is and are comfortable with it. If you want to read more on JSON, the following link will take you over to Wikipedia where you can read more – http://en.wikipedia.org/wiki/JSON.

A very simple JSON string looks as follows:

{"forename" : "Phil", "surname" : "Curnow", "age" : 41}

We have a simple set of Name/Value pairs. In order to work with this data, we certainly don’t want to start writing code to parse the name/value pairs, its just not worth it. Ideally we would like to return this data in an object. To do this we can deserialize the JSON string. The following code snippet will explain how to do this. In order for this code to work, ensure that you have the following using’s at the top of your code:

using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

The chances are, you will also need to add a reference to System.Runtime.Serialization in your Visual Studio project. With all of this done, you should now be able to work with the following code.

Creating a Person Class

As already mentioned, we want to deserialize the JSON string into an object. In order to do this, we obviously need to create a class, we will call this class Person. Pay particular attention to the attributes used within the class declaration and the properties.

[DataContract]
class Person
{
    [DataMember]
    public string forename { get; set; }
    [DataMember]
    public string surname { get; set; }
    [DataMember]
    public int age { get; set; }
}

You will see that our properties are named exactly the same as the name in the name/value pairs in the JSON string. We can then write the following code to deserialize the string.

string jsonString = @"{""forename"" : ""Phil"", ""surname"" : ""Curnow"", ""age"" : 41}";

DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person)); 
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); 
Person obj = (Person)ser.ReadObject(stream);

Our deserialized string is now in the object obj (which is of the type Person). With this in mind, we can access the properties of the object by simply using obj.forename, obj.surname, etc. To make life a little easier, you could always set the object obj as follows:

var obj = (Person)ser.ReadObject(stream);

Working with an Array of JSON Objects

What do we do if we have more than one person defined in our JSON string, such as:

[{"forename" : "Phil", "surname" : "Curnow", "age" : 41},{"forename" : "Lorna", "surname" : "Curnow", "age" : 44}]

As it stands, our deserialization code will not work with this JSON string, we need a little tweaking. Basically, we need to return a list of People objects, so our code will now look as follows:

string jsonString = @"[{""forename"" : ""Phil"", ""surname"" : ""Curnow"", ""age"" : 41},{""forename"" : ""Lorna"", ""surname"" : ""Curnow"", ""age"" : 44}]";

DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<Person>)); 
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); 
var obj = (List<Person>)ser.ReadObject(stream);

Notice that we have now specified List<Person> in our code. We can then use the following to display the person data to the console:

foreach (Person p in obj)
    Console.WriteLine("Forename: {0} - Surname: {1}", p.forename, p.surname);

Now this is all very well, but do we really want to write that same block of code each time we want to work with a different data type? Well, probably not!! and this is where a quick conversion of the code to a generic method comes in handy. By simply creating the following generic method, we now have a piece of code that should work with any data type:

public static T DeserializeJSon<T>(string jsonString) 
{
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
    MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
    T obj = (T)ser.ReadObject(stream);
    return obj;
}

Rewriting the above deserialization now becomes as simple as this:

var obj = DeserializeJSon<Person>(jsonString);

or

var obj = DeserializeJSon<List<Person>>(jsonString);

A More Complex JSON String

Whilst I am not going to cover the multitude of different JSON strings you could work with, there is one more I want to show you. Consider the following string (formatted for easier reading):

{
    "forename":"Phil",
    "surname":"Curnow",
    "age":41,
    "address":
    {
        "line1":"21 High Street",
        "line2":"Anyplace, AnyTown, AN1 1AB"
    }
}

We now have an address included, which is made up of name/value pairs in its own right. So how do we deserialize this kind of string? Well, its actually very easy. All we have to do is create a new class for the address data and add a property of the type address to the Person class, as follows:

[DataContract]
class Address
{
    [DataMember]
    public string line1 { get; set; }
    [DataMember]
    public string line2 { get; set; }
}

Our Person class is then modified as follows:

[DataContract]
class Person
{
    [DataMember]
    public string forename { get; set; }
    [DataMember]
    public string surname { get; set; }
    [DataMember]
    public int age { get; set; }
    [DataMember]
    public Address address { get; set; }
}

The address is then handled correctly and the address lines placed in the address property.

Naming Class Properties Differently to JSON Names

You will more than likely want to name your class properties differently to their JSON counterparts. Consider the possibility of having the name/value pair current-account-balance:210.00. Personally I would not want a property in my class named current-account-balance!! To overcome this, we can slightly modify the [DataMember] attribute declaration to the following:

[DataMember (Name="current-account-balance")]
public decimal AccountBalance { get; set; }

This then defines a property in our class called AccountBalance that will contain the value of the current-account-balance.

Serializing Data to JSON

As you can guess, there is an opposite to deserializing, which is serializing. Consider the fact that we have created a Person object, or a list of Person objects and we want to convert this to a JSON string and return this from an API call. As with the deserialization, we need to write a generic method that will convert any type to its JSON equivalent. This method is as follows:

public static string SerializeJSon<T>(T t)
 {     
    MemoryStream stream = new MemoryStream();
    DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(T));
    DataContractJsonSerializerSettings s = new DataContractJsonSerializerSettings();
    ds.WriteObject(stream, t);
    string jsonString = Encoding.UTF8.GetString(stream.ToArray());
    stream.Close();
    return jsonString;
}

If we then create a Person object as follows:

Person p = new Person
{
    forename = "Phil",
    surname = "Curnow",
    age = 41,
    address = new Address { line1 = "21 High Street", line2 = "Anyplace, AnyTown, AN1 1AB" }
};

We can simply convert it to a JSON string using the method call:

string jsonString = SerializeJSon<Person>(p);

Or with a list of Person objects, as follows:

List<Person> people = new List<Person>();
people.Add(new Person ...  );
people.Add(new Person ... );

string jsonString = SerializeJSon<List<Person>>(people);

Conclusion

As you can see, working with JSON data in C# is not at all difficult with the facilities built into the .NET Framework. If you are planning to work with JSON data to a larger extent, it is worth spending time investigating JSON further to become comfortable with looking at the data and being able to model it using classes.

Advertisements

19 thoughts on “Serializing and Deserializing JSON in C#

  1. Thank you for the explanation, but I was wondering… Why not simply use the code above?
    MyJsonClass obj = new JavaScriptSerializer().Deserialize(jsonString);

  2. This is an excellent article. Concise, thorough, and exactly what I needed to find. Thank you.

    I would like to mention that the System.Runtime.Serialization.Json namespace lives in System.ServiceModel.Web.dll (this is mentioned in the MSDN documentation for .NET 3.5 and .NET 4.0, but not for .NET 4.5) rather than logically being in the System.Runtime.Serialization dll. Anyhow, you actually need both references to use this.

  3. Does anyone know how to serialize and deserialize an array of addresses for a person? How would you create that? For instance if Phil Curnow owned 3 properties and the schema allowed to track them all:

    {
    “forename”:”Phil”,
    “surname”:”Curnow”,
    “age”:41,
    “address”:
    [ {
    “line1″:”21 High Street”,
    “line2″:”Anyplace, AnyTown, AN1 1AB”
    },
    {
    “line1″:”22 High Street”,
    “line2″:”Anyplace, AnyTown, AN1 1AB”
    },
    {
    “line1″:”23 High Street”,
    “line2″:”Anyplace, AnyTown, AN1 1AB”
    }]
    }

    What changes would have to be made to the above code to create this JSON query and read it back for storage? Thanks

  4. Congratulations for the post. Just one question (maybe too late). In “Serializing Data to JSON”, is it necessary to declare de DataContractSerializerSettings() if is not used?

    Thanks

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