Computer Beacon  

Blog

Optimized Json Toolkit: v3.0

Posted on 2/21/2012

Today I am proud to present to you the new Json Toolkit v3.0. This version brings significant performance improvement by using a completely redesigned parsing algorithm. The algorithm is much faster and has a speed up of more than 900% (i.e. 10 times faster) than the previous version.

Here are some of the performance comparisons between v2.1 and v3.0 using real JSON data. The running time is measured by looping the parse operation from 1000 to 100000 times (depending on length and complexity of the data).

Sample Data v2.1 v3.0 Speed up
Sample JSON from wiki 11684 ms 1654 ms 606%
Serialized Java servlet 84115 ms 10125 ms 731%
Bing Api object 29296 ms 3260 ms 798%
Facebook Graph object 8030 ms 793 ms 913%

The new algorithm removes unnecessary function calls and also take into consideration the fact that most data in real world scenarios are either string or integer data. Data from Facebook Graph Api are often wrapped in many layers of JSON objects and arrays, which explains why it has the highest speed up among all test data.

Json Toolkit v3.0 is available for download at CodePlex: http://jsontoolkit.codeplex.com/ . The library is fully compatible with the old version as no functionality has changed; simply replace the dll file and recompile the application. The new library is also tested against 50 different test cases with 100% pass.

Comment on this post


Json Toolkit 2.1 Update

Posted on 1/27/2012

The Json Toolkit has been updated to version 2.1 to fix a bug about deserializing data containing null values as reported by developers. The new library and the source code can be downloaded at CodePlex:  http://jsontoolkit.codeplex.com/ . Since Facebook Graph Toolkit does not use the deserialize feature at the moment, this fix does not affect applications that use FGT.

Comment on this post


Deserializing JSON data in C#

Posted on 1/23/2012

Many web services today return data in JSON format instead of XML format because of the reduced overhead. APIs of Facebook and Bing are two examples. The new JSON Toolkit 2.0 supports an easy to use model for deserializing JSON data to C# classes, and can be used directly to convert JSON data to strongly typed data types. Consider the following JSON:

{
    "Height":1080,
    "Width":1920,
    "Name":"HD Frame"
}

Together with a C# class that corresponds to this data:

class ImageInfo{
    [JsonElement]
    public int Height { get; set; }

    [JsonElement]
    public int Width { get; set; }

    [JsonElement]
    public string Name { get; set; }

    public ImageInfo() { }
}

We can easily convert the JSON object to an ImageInfo object with two lines of code:

JsonObject JO = new JsonObject("{\"Height\":1080,\"Width\":1920,\"Name\":\"HD Frame\"}");
ImageInfo II = JO.Deserialize<ImageInfo>(true);

The class that is deserialized to must have a public parameterless constructor.

Note the [JsonElement] attribute. The name of the property in the class must match that in the JSON data. The names are case sensitive. The boolean parameter specifies whether only those properties marked with a [JsonElement] attribute should be processed. For example, if the [JsonElement] attribute of the Name property does not exist, and the deserialize code is written this way:

ImageInfo II =JO.Deserialize<ImageInfo>(true);

Then the Name property will not be set, even though there is a matching set of values in the original JSON data.

However, if the parameter is passed as false, then the value of all properties with a matching name in the JSON data will be specified, and the [JsonElement] attribute is ignored.

Naming JSON elements

If you do not wish to use the same name for the properties in the class as those in the JSON data, you can specify the Name of [JsonElement] attribute.

class ImageInfoSpecial{
    [JsonElement(Name="Height")] //Match this property to the "Height" value in the JSON data
    public int H { get; set; }

    [JsonElement(Name="Width")] //Match this property to the "Width" value in the JSON data
    public int W { get; set; }

    [JsonElement]
    public string Name { get; set; }

    public ImageInfoSpecial() { }
}

In this ImageInfoSpecial class we renamed the "Height" property to "H" property, and the "Width" property to the "W" property. After deserializing, the value of the "H" property will be 1080, and the value of the "W" property will be 1920.

Deserializing JSON array

JSON Array are always deserialized to an List<T> object. The type T is specified as a generic argument to the JsonArray's Deserialize method. Below are some examples.

JsonArray JA = new JsonArray("[1,20,3000]");
List<int> Items = JA.Deserialize<int>();

JsonArray JA = new JsonArray("[\"String\",\"Value\",\"Key\"]");
List<string> Items = JA.Deserialize<string>();

JsonArray JA = new JsonArray("[[7,8,9],[4,5,6],[1,2,3],[0],[]]");
List<List<int>> Items = JA.Deserialize<List<int>>();

Note that in the third example we have a nested JSON array. Nested arrays, or JSON objects nested inside JSON arrays also work. The JSON library will recursively deserialize the items inside the array until the value is not encapsulated in a JSON array or JSON object anymore.

Mixing JSON arrays with JSON object

Besides having a JSON object inside a JSON array, it is also possible to have a JSON array as one of the values inside a JSON object.

{
    "Height":1080,
    "Width":1920,
    "Name":"HD Frame",
    "Ratings":[
        1,
        2,
        3,
        4,
        5
    ]
}

class ImageInfoComplete{
    [JsonElement]
    public int Height { get; set; }

    [JsonElement]
    public int Width { get; set; }

    [JsonElement]
    public string Name { get; set; }

    [JsonElement]
    public List<int> Ratings { get; set; }

    public ImageInfoComplete() { }
}

The deserializing steps are the same as before.

JsonObject JO = new JsonObject("{\"Height\":1080,\"Width\":1920,\"Name\":\"HD Frame\",\"Ratings\":[1,2,3,4,5]}");
ImageInfoComplete II = JO.Deserialize<ImageInfoComplete>(true);

Comment on this post


Creating JsonObjects in C#

Posted on 1/15/2012

In this blog post I'll talk more about the JSON Toolkit. JSON encoded strings are widely used on the internet for data transmission or storage. Version 2.0 of JSON Toolkit adds features including creating and manipulating JSON objects. But first, let's talk about parsing JSON strings.

Parsing JSON strings

Let's say I have a text file with the following content:

{ "Image": { "Width": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "http://www.example.com/image/481989943", "Height": 125, "Width": 100 }, "IDs": [116, 943, 234, 38793] } }

It's easy to convert the above string into an instance of JsonObject by calling its constructor.

JsonObject JO = new JsonObject(File.ReadAllText(@"D:\Some Path Here\Sample.txt"));

The string can come from anywhere, such as text files, web services (as is the case in Facebook Graph Toolkit), or even user input. As long as it is a valid JSON string, the library can parse it. Note that the JSON Toolkit does not support number values using the "e" notation at this point.

Creating JSON objects

It is also possible to add key-value pairs to a JSON object starting with an empty one. The code below shows how to create a JSON object with content almost identical to the one above.

JsonObject ImageJO = new JsonObject();
ImageJO.Add("Width", 800);
ImageJO.Add("Height", 600);
ImageJO.Add("Title", "View from 15th floor");

JsonObject ThumbJO = new JsonObject();
ThumbJO.Add("Url", "http://www.example.com/image/481989943");
ThumbJO.Add("Height", 125);
ThumbJO.Add("Width", 100);
ImageJO.Add("Thumbnail", ThumbJO); //Nested JsonObject here

JsonArray JA = new JsonArray();
JA.Add(116);
JA.Add(943);
JA.Add(234);
JA.Add(38793);
ImageJO.Add("IDs", JA); //Nested JsonArray here

Each "property" in a JsonObject is associated with a key, so the keys must be unique. The type of each property can be one of the followings: string, any number types in C#, bool, a JsonArray or JsonObject. Elements in JsonObject are unordered and are only identified by keys. Elements in JsonArray however are ordered.

The above code almost produces a JsonObject same as the parse example. The only step missing is to put the image object inside another JsonObject.

JsonObject JO = new JsonObject();
JO.Add("Image", ImageJO);

Output a JsonObject

To output a JsonObject (e.g. save it in a text file or database), simply call its ToString() method.

The output string is a string identical to the sample above, but without all the unnecessary white spaces. When parsing, the JSON Toolkit accepts an arbitary number of white spaces (as well as new lines) between JSON syntax characters. The ToString() method always produce the shortest string that represents the data, thus there will be no white spaces.

The string can be later retrieved to create another instance of JsonObject at runtime which represents identical data. The following code thus duplicates an instance of JsonObject by creating another instance with the exact same data:

JsonObject SecondJO = new JsonObject(FirstJO.ToString());

Comment on this post


Custom Graph Apis with Facebook Graph Toolkit

Posted on 1/12/2012

Since release 2.5, the GetJsonFromFacebookObject method in FGT is made public instead of internal. This means developers can choose to interpret Facebook's response their own besides using FGT's strongly typed classes. This flexibility allows developers to use new Graph Api data types that are not implemented in the library when they're made available by Facebook. The following shows an example.

JsonObject JO = Facebook_Graph_Toolkit.Helpers.WebResponseHelper.GetJsonFromFacebookObject("me", AccessToken);

To display the returned JsonObject in a structured format, developers may call its ToHtmlString() method.

Response.Write(JO.ToHtmlString());

The result is an easy to read html.

{
    "id":"123456789",
    "name":"Secret user name......",
    .........
}

More customized Api calls

Since the JsonToolkit is a "stand alone" library itself that can be used without FGT, it can be used to parse any data that is in JSON format. The following examples shows an api call specifying the returned fields.

string Address = string.Format("https://graph.facebook.com/me?access_token={0}&fields=id,name,birthday", AccessToken);
WebClient WC = new WebClient();
JsonObject JO = new JsonObject(WC.DownloadString(Address));
string ID = JO["id"].ToString();
string Name = JO["name"].ToString();
DateTime Birthday = Convert.ToDateTime(JO["birthday"].ToString());

Thus, FGT and JsonToolkit can be used together to cover virtually every api call provided by Facebook. FGT includes most of these data types, as well as implementations to handle exceptions, test AccessTokens, decode the Base64-encoded response in Canvas Page etc. Developers however are free to extend the functionality beyond that.

Comment on this post