Computer Beacon  

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);


You must be logged in through Facebook to write comments.

Comments

There are no comments at the moment