Thursday, September 20, 2012

Convert JSON to .Net Entities – Alternate Way


Often, there are multiple ways to do the same thing in code.

In my previous post, I demonstrated how to convert JSON to .Net entities using the classes in System.Runtime.Serialization and System.Runtime.Serialization.Json namespace.

The alternate is to use classes in Windows.Data.Json namespace.
http://msdn.microsoft.com/en-us/library/windows/apps/windows.data.json.aspx

I came across this style while doing the Contoso Cookbook lab examples, which has the original code.

Below is the code snippet of converting the JSON String to .Net Entitity classes. This example uses the entity classes from previous example. However, it populates each and every property by individually assigning it values. While its more lines of code than the previous example, it can be useful when your .Net Class structure differs from the JSON structure.
Namespaces you need to refer:
using Windows.Data.Json;

Code:
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\"}}]}";

RootObject fbFriends = ConvertJSONToEntity(jsonFriendsString);
 
//Get Friends List
var friendsList = fbFriends.data;

//Loop Through Friends List
foreach (Datum friend in friendsList)
{
       //Do Something
}
 
Convert JSON to .Net Entities:
private RootObject ConvertJSONToEntity(string JSONString)
{
            //Create .Net Entity Classes to populate
            RootObject fbFriends = new RootObject();
            fbFriends.data = new List<Datum>();

            //Parse the JSON String to an JSON Object
            JsonObject objJSON = JsonObject.Parse(JSONString);

            var objElement = objJSON.ElementAt(0);

            JsonArray array = objElement.Value.GetArray();

            foreach (var item in array)
            {
                Datum friend = new Datum();

                var obj = item.GetObject();

                foreach (var key in obj.Keys)
                {

                    IJsonValue val;
                    if (!obj.TryGetValue(key, out val))
                        continue;

                    switch (key)
                    {
                        case "uid":
                            friend.uid = (long)val.GetNumber();
                            break;

                        case "first_name":
                            friend.first_name = val.GetString();
                            break;

                        case "last_name":
                            friend.last_name = val.GetString();
                            break; 

                        case "pic_square":
                            friend.pic_square = val.GetString();
                            break;

                        case "pic_big":
                            friend.pic_big = val.GetString();
                            break;

                        case "timezone":
                            var objTimeZone = val.ValueType;
                            if (objTimeZone != JsonValueType.Null)
                            {
                                friend.timezone = val.GetObject();
                            }
                            else
                            {
                                friend.timezone = "";
                            }

                            break;

                        case "current_location":
                            JsonObject loc = val.GetObject();
                            CurrentLocation curLoc = new CurrentLocation();

                            curLoc.city = loc.GetNamedString("city");
                            curLoc.country = loc.GetNamedString("country");
                            curLoc.zip = loc.GetNamedString("zip");
                            curLoc.name = loc.GetNamedString("name");
                            curLoc.id = loc.GetNamedNumber("id").ToString();

                            friend.current_location = curLoc;
                            break;
                    }//End Switch

                }//End Inner For Each keys

                //Add Object to List    
                fbFriends.data.Add(friend);

            }//end outer foreach

            //Return List of Objects
            return fbFriends;
        }

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