Real world json parsing in WinRT

Parsing text is everywhere these days. Having a human readable-friendly data format is very compelling, and json one of the big players in this area. I often find myself copying the parsing code from a previous project whenever I need to parse json, and I would just like to have the different options in one place for my own future reference. Hopefully helps a colleague or two at Jayway, or someone else out there in the world. Out of curiosity, I added some time measurements.

copy-paste

The code for this experiment can be found on my github, and consist of a Win8.1 class lib for the parsing, one Win8.1 class lib for the unit tests, and one Win8.1 app that does nothing Smile Go figure.

The parsers

Today’s “contenders” are:

I tried adding ServiceStack.Text too, but the PCL did not have support for my Windows 8.1 class library in this test, so it got left out of this experiement.

The json

The data comes from the Swedish national radio network Sverige Radio, and is the data that feeds my personal on-demand news radio app for Windows Phone: Ekot. Download Ekot here if you have not already Winking smile

Episodes are listed with some data for each, and looks like this:

    "copyright": "Copyright Sveriges Radio 2013. All rights reserved.",
    "episodes": [{
        "id": 297558,
        "title": "Ekonyheter",
        "description": "Lyssna på de senaste nyhetssändningarna
 och arkivet med Kvart-i-fem-Ekot",
        "url": "http://sverigesradio.se/sida/avsnitt/297558?programid=4540",
        "imageurl": "http://sverigesradio.se/diverse/appdata/isidor/images/
news_images/83/2874631_512_512.jpg",
        "program": {
            "id": 4540,
            "name": "Ekot"
        },
        "publishdateutc": "/Date(1387231200000)/",
        "broadcast": {
            "availablestoputc": "/Date(1389823620000)/",
            "playlist": {
                "duration": 420,
                "publishdateutc": "/Date(1387231200000)/",
                "id": 4797952,
                "url": "http://sverigesradio.se/api/radio/radio.aspx?
type=broadcast&id=4797952&codingformat=.m4a&metafile=asx&quality=hi",
                "statkey": "/app/avsnitt/nyheter (ekot)[k(83)]/ekot[p(4540)]/
ekonyheter 20131216 23:00[e(297558)]"
            },
            "broadcastfiles": [{
                "duration": 420,
                "publishdateutc": "/Date(1387231200000)/",
                "id": 4797952,
                "url": "http://sverigesradio.se/topsy/ljudfil/4797952-hi.m4a",
                "statkey": "/app/avsnitt/nyheter (ekot)[k(83)]/ekot[p(4540)]/
ekonyheter 20131216 23:00[e(297558)]"
            }]
        }
    },
    {
        "id": 297534,
        "title": "Dagens eko kvart i fem 16 december",
...

The parsing

Here’s how the parsing of the title from each episode looks like. Disclaimer: this code is not optimized or made perfect, goal is to be comparable between the methods and easy to read.

The common interface that I’ve let my parser classes implement is:

namespace JsonParsing.Core
{
    public interface IJsonParser
    {
        IJsonData Parse(string json);
    }

    public interface IJsonData
    {
        IJsonItem[] Items { get; set; }
    }

    public interface IJsonItem
    {
        string Title { get; set; }
    }
}

JsonObject

public IJsonData Parse(string json)
{
    var jsonObject = Windows.Data.Json.JsonObject.Parse(json);
    var episodes = jsonObject.GetObject().GetNamedArray("episodes");

    var result = new JsonData();
    var jsonItems = episodes.Select(
e => new JsonItem(e.GetObject().GetNamedString(("title"))));
    result.Items = jsonItems.Cast<IJsonItem>().ToArray();

    return result;
}

Json.NET – DeserializeObject

Worth mentioning, this method requires statically typed classes for the entire json structure. Fortunately, this can easily be generated by e.g. json2csharp.

public IJsonData Parse(string json)
{
    //using http://json2csharp.com/

    var obj = JsonConvert.DeserializeObject<RootObject>(json);

    if (obj == null)
        return null;

    var items = obj.episodes.Select(e => new JsonItem(e.title));
    var jsonItems = items.Cast<IJsonItem>().ToArray();
    var result = new JsonData
    {
        Items = jsonItems
    };

    return result;
}

Json.NET – JObject.Parse

public IJsonData ParseWithJObjectParse(string json)
{
    return ParseWithJObjectParse(json, "episodes", "title");
}

public IJsonData ParseWithJObjectParse(string json, string episodesName, string titleName)
{
    var obj = JObject.Parse(json);

    if (obj == null)
        return null;

    var items = obj.GetValue(episodesName).Select(
e => new JsonItem(((JObject)e).GetValue(titleName).ToString()));

    var jsonItems = items.Cast<IJsonItem>().ToArray();
    var result = new JsonData
    {
        Items = jsonItems
    };

    return result;
}

Simple.Json

Simple.json has a dictionary-way of parsing too, I left that out.

public IJsonData Parse(string json)
{
    dynamic jsonObject = SimpleJson.DeserializeObject(json);
    List<object> episodes = jsonObject.episodes;
    var items = episodes.Select(e => new JsonItem(((dynamic)e).title));

    var result = new JsonData
    {
        Items = items.Cast<IJsonItem>().ToArray()
    };

    return result;
}

The time measurements

I iterated each parser 1000 times. As you can see, Json.NET is the clear winner in this case. What surprised me though, was that parsing everything which DeserializeObject does, was faster than just parsing the title value.

Running 1000 iterations...
can_parse_with_json_net_deserialize_object                  2.3598949 ms/parse round
can_parse_with_json_net_jobject_parse_static_strings        3.4563563 ms/parse round
can_parse_with_json_net_jobject_parse_strings_as_parameters 3.7103755 ms/parse round
can_parse_with_json_net_jobject_parse_strings_in_linq_query 3.6543690 ms/parse round
can_parse_with_msft_json_object                             8.7019841 ms/parse round
can_parse_with_simple_json_dictionary                       6.9238526 ms/parse round
Finished 1000 iterations in 00:00:28.8088353

Summary

Json parsing is very simple, and the code above hopefully helps some of us out there who just wants to get a jump start into parsing their data.

Code can be found on my github.

I wish you a happy 2014!

This Post Has 5 Comments

  1. I have one silly question not related to JSON, why you have used interface viz IJsonParser, IJsonParser & IJsonParser? What is the specific reason?

  2. Interesting post, thank you for sharing.

    As I’m interested to know about how it performs (in speed, memory consumption, warm up, etc) on platforms other than “vanilla Windows” + the full .NET, just thought I could share about this little one of mine:

    https://github.com/ysharplanguage/FastJsonParser#Performances

    As for the input JSON you used for your experiment (and assuming the parser can even compile) I’m confident it should normally be able to grok it fine, whether deserializing into POCOs or loosely typed dictionaries + lists – exception made for the dates (it doesn’t support the Microsoft “/Date(…)/” syntax, but instead just the ISO8601-like one – “yyyy-mm-dd … etc”)

    Some encouraging early results were observed on Android at least, besides the desktop:

    http://forums.xamarin.com/discussion/comment/38955/#Comment_38955

    Cheers, (and happy new year :)

  3. This is a great article. It helped me parse my jsonstring. Thanks again.

Leave a Reply

Close Menu