Saturday, September 15, 2012

Convert JSON to .Net Entities


JSON v/s XML:

As I mentioned in my previous blog post, JSON has emerged as the new serializable data transfer  format while writing Web Services in both the Enterprise and the Consumer world. Compared to XML, JSON is light weight and hence fast, when transmitted over the wire. Search for "JSON v/s XML" on the internet using your favorite Search Engine and you will find a number of blogs on this topic. This blog is not about JSON v/s XML.

This blog will discuss how to convert a JSON sting into .Net Entities.
 
Why do we need to convert JSON to .NET Entities?
JSON is normally used with JavaScript. However, it can also be used with .Net.
.Net code can also consume JSON Web Services.
In my case, I was writing a .Net App (Win 8 Metro Style) using XAML/C# and calling Facebook Web Services using the Facebook Query Language(FQL). FQL returns data in JSON format, and I had to convert to .Net.
 
How do we do it?
Step 1: Create equivalent .Net Classes
Step 2: Deserialize  JSON data to .Net Objects
 
How do we really do it?
Step 1: You can create classes  by hand, however, I will suggest using this handy online tool that convers JSON to .Net classes
Note: You need to add DataContract and DataMember attributes to generated class

Input JSON String

{"data":[{"uid":560275290,"first_name":"Vinay","last_name":"Bhatia","pic_square":"http://profile.ak.fbcdn.net/hprofile-ak-snc7/371731_560275290_925165134_q.jpg","pic_big":"http://profile.ak.fbcdn.net/hprofile-ak-snc7/371731_560275290_925165134_n.jpg","timezone":null,"current_location":{"city":"Singapore","country":"Singapore","zip":"","id":101883206519751,"name":"Singapore, Singapore"}},{"uid":702608824,"first_name":"Santosh","last_name":"Singh","pic_square":"http://profile.ak.fbcdn.net/hprofile-ak-ash4/275768_702608824_1698652029_q.jpg","pic_big":"http://profile.ak.fbcdn.net/hprofile-ak-ash4/275768_702608824_1698652029_n.jpg","timezone":null,"current_location":{"city":"Edison","state":"New Jersey","country":"United States","zip":"","id":109295752421654,"name":"Edison, New Jersey"}},{"uid":100001987004026,"first_name":"Mayur","last_name":"Udernani","pic_square":"http://profile.ak.fbcdn.net/hprofile-ak-prn1/174061_100001987004026_5522672_q.jpg","pic_big":"http://profile.ak.fbcdn.net/hprofile-ak-prn1/161176_100001987004026_3945963_n.jpg","timezone":null,"current_location":{"city":"London","state":"England","country":"United Kingdom","zip":"","id":106078429431815,"name":"London, United Kingdom"}}]}

 
Output of json2csharp.com:

public class CurrentLocation

{
    public string city { get; set; }
    public string country { get; set; }
    public string zip { get; set; }
    public object id { get; set; }
    public string name { get; set; }
    public string state { get; set; }
}

public class Datum
{
    public long uid { get; set; }
    public string first_name { get; set; }
    public string last_name { get; set; }
    public string pic_square { get; set; }
    public string pic_big { get; set; }
    public object timezone { get; set; }
    public CurrentLocation current_location { get; set; }
}


Namespaces you need to refer:

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


Classes with required Attributes:

 [DataContract]
    public class RootObject
    {

        [DataMember]
        public List<Datum> data { get; set; }
    }


[DataContract]
public class CurrentLocation
{
 [DataMember]
    public string city { get; set; }

 [DataMember]
    public string country { get; set; }

 [DataMember]
    public string zip { get; set; }

 [DataMember]
    public object id { get; set; }

 [DataMember]
    public string name { get; set; }

 [DataMember]
    public string state { get; set; }

}

[DataContract]
public class Datum
{

 [DataMember]
    public long uid { get; set; }

 [DataMember]
    public string first_name { get; set; }

 [DataMember]
    public string last_name { get; set; }

 [DataMember]
    public string pic_square { get; set; }

 [DataMember]
    public string pic_big { get; set; }

 [DataMember]
    public object timezone { get; set; }

 [DataMember]
    public CurrentLocation current_location { get; set; }

}


Convert JSON to .Net Entitiies:

Now that you have your .Net classes ready, converting JSON to .Net using built in classes of Win RT is only a few lines of code.  I wrote this piece of code around 3 months back, when Window 8 RT was in consumer preview and there was no good documentation on how to use the classes.
 
 Here is an end to end code, in case want to debug it and test it out within a .Net application.

//In real world, populate jsonFriendsString by making a web service call.

 " has been escaped as \" in the code below. You wont need the escape character while consuming  from web services.

            string jsonFriendsString = "{\"data\":[{\"uid\":560275290,\"first_name\":\"Vinay\",\"last_name\":\"Bhatia\",\"pic_square\":\"http://profile.ak.fbcdn.net/hprofile-ak-snc7/371731_560275290_925165134_q.jpg\",\"pic_big\":\"http://profile.ak.fbcdn.net/hprofile-ak-snc7/371731_560275290_925165134_n.jpg\",\"timezone\":null,\"current_location\":{\"city\":\"Singapore\",\"country\":\"Singapore\",\"zip\":\"\",\"id\":101883206519751,\"name\":\"Singapore, Singapore\"}},{\"uid\":702608824,\"first_name\":\"Santosh\",\"last_name\":\"Singh\",\"pic_square\":\"http://profile.ak.fbcdn.net/hprofile-ak-ash4/275768_702608824_1698652029_q.jpg\",\"pic_big\":\"http://profile.ak.fbcdn.net/hprofile-ak-ash4/275768_702608824_1698652029_n.jpg\",\"timezone\":null,\"current_location\":{\"city\":\"Edison\",\"state\":\"New Jersey\",\"country\":\"United States\",\"zip\":\"\",\"id\":109295752421654,\"name\":\"Edison, New Jersey\"}},{\"uid\":100001987004026,\"first_name\":\"Mayur\",\"last_name\":\"Udernani\",\"pic_square\":\"http://profile.ak.fbcdn.net/hprofile-ak-prn1/174061_100001987004026_5522672_q.jpg\",\"pic_big\":\"http://profile.ak.fbcdn.net/hprofile-ak-prn1/161176_100001987004026_3945963_n.jpg\",\"timezone\":null,\"current_location\":{\"city\":\"London\",\"state\":\"England\",\"country\":\"United Kingdom\",\"zip\":\"\",\"id\":106078429431815,\"name\":\"London, United Kingdom\"}}]}";

 

            //Start JSON DeSerializaton

            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(RootObject));

 
            //Convert string to stream
            //GetyBytes method is used to to create a byte array
            byte[] byteArray = Encoding.Unicode.GetBytes(jsonFriendsString);

 
            MemoryStream stream = new MemoryStream(byteArray);

            stream.Position = 0;


            //DeSearialize Stream to Object
            RootObject fbFriends = (RootObject)serializer.ReadObject(stream);

            //End JSON DeSerializaton

 
            //Get Friends List
            var friendsList = fbFriends.data;

            //Loop Through Friends List
            foreach (Datum friend in friendsList)
            {
                //Do Something
            }

Any Other Options?
Part 2: In my next blog post, I show an alternate way of doing the same thing.
http://vinaybhatia.blogspot.in/2012/09/convert-json-to-net-entities-alternate.html 

No comments: