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(ListNotice that we have now specified List)); MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); var obj = (List )ser.ReadObject(stream);
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 DeserializeJSonRewriting the above deserialization now becomes as simple as this:(string jsonString) { DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); T obj = (T)ser.ReadObject(stream); return obj; }
var obj = DeserializeJSonor(jsonString);
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 aPerson
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 SerializeJSonIf we then create a Person object as follows:(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; }
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 = SerializeJSonOr with a list of Person objects, as follows:(p);
ListSource URL: https://philcurnow.wordpress.com/2013/12/29/serializing-and-deserializing-json-in-c/people = new List (); people.Add(new Person ... ); people.Add(new Person ... ); string jsonString = SerializeJSon >(people);
0 comments:
Post a Comment