Breaking News
Loading...
July 31, 2015

SERIALIZING AND DESERIALIZING JSON IN C#

9:36 AM
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)); 
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); 
var obj = (List)ser.ReadObject(stream);
Notice that we have now specified List 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(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(jsonString);
or
var obj = DeserializeJSon>(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)
 {     
    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(p);
Or with a list of Person objects, as follows:
List people = new List();
people.Add(new Person ...  );
people.Add(new Person ... );

string jsonString = SerializeJSon>(people);
Source URL: https://philcurnow.wordpress.com/2013/12/29/serializing-and-deserializing-json-in-c/

0 comments:

Post a Comment

 
Toggle Footer