Using the Little-known Built-in .NET JSON Parser

You wouldn’t know it, but an alternative to the multitude of JSON parsers built for the .NET platform is to use the one built into the core libraries of .NET itself. It feels like it flies under the radar a bit, which I suspect is due to it not being listed on the JSON site. The main advantage of preferring the built-in library is that there’s one less dependency to track, but a bonus is that we can easily deserialize from multiple formats because the parser works by treating JSON like XML, as I’ll discuss in a moment.

Use the JSON deserializer by building an XmlReader instance from the static class JsonReaderWriterFactory, then using your favorite XML querying technique to extract data (I use XPath below). JSON classes come from the System.Runtime.Serialization.Json namespace, accessible by adding a project reference to System.Runtime.Serialization.

string filename = args[0];
byte[] buffer = File.ReadAllBytes(filename);
XmlReader reader = 
    JsonReaderWriterFactory
        .CreateJsonReader(buffer, new XmlDictionaryReaderQuotas());

XElement root = XElement.Load(reader);

// The fields we'd like to extract
XElement form   = root.XPathSelectElement("//form");
XElement status = root.XPathSelectElement("//status");
XElement type   = root.XPathSelectElement("//type");

// Field set
IEnumerable<XElement> fields = root.XPathSelectElements("//fields/*");

If any of the elements we selected didn’t exist, the corresponding XElement will hold a null. This program will read a simple JSON document like the following:

{
    "form":   13, 
    "status": "NEW", 
    "type":   "FORM", 
    "fields": {
        "field": { "key": 50, "value": 1 } 
    }
}

Now for the interesting part! Notice in the code snippet above that we load our JSON document with an XmlReader and treat it almost exactly like XML. We can leverage this property by rewriting our simple parser to read either a JSON or an XML document.

string filename = args[0];
byte[] buffer = File.ReadAllBytes(filename);
XmlReader reader = new FileInfo(filename).Extension.ToLower() == "xml"
    ? XmlReader.Create(new MemoryStream(buffer)) 
    : JsonReaderWriterFactory
        .CreateJsonReader(buffer, new XmlDictionaryReaderQuotas());

XElement root = XElement.Load(reader);

// The fields we'd like to extract
XElement form   = root.XPathSelectElement("//form");
XElement status = root.XPathSelectElement("//status");
XElement type   = root.XPathSelectElement("//type");

// Field set
IEnumerable<XElement> fields = root.XPathSelectElements("//fields/*");

Now our parser will work fine with an XML document that looks like this:

<message>
    <form>13</form>
    <status>ACC</status>
    <type>NOOP</type>
    <fields>
        <field>
            <key>50</key>
            <value>1</value>
        </field>
    </fields>
</message>

Obviously the similarity of the two types of documents breaks down when we start using more complex features such as JSON’s array support, or XML’s namespaces; but it sure works great for simple cases.

Posted on December 29, 2010 from Calgary

About

My name is Brandur. I'm a polyglot software engineer and part-time designer working at Heroku in San Francisco, California. I'm a Canadian expat. My name is Icelandic. Drop me a line at brandur@mutelight.org.

Aside from technology, I'm interested in energy and how it relates to our society, travel, longboarding, muay thai, symphonic metal, and the guitar.

If you liked this article, consider finding me on Twitter.