Thursday, January 26, 2012

JSON for the truly frightened ex-Silverlight developer.

So you're a frightened .Net developer.

More specifically, you're a frightened client-side, non-Javascript Silverlight .Net developer.  For a few years, Microsoft had shielded you from the tribulations of Javascript development to create rich client web applications with it's robust Flash competitor.

Suddenly Microsoft starts getting flaky on you, and starts beating the HTML5 drum very loudly, which as everyone knows relies heavily on Javascript.  Silverlight isn't so shiny anymore, and Microsoft silently admits that it's maybe time to get familiar with "standards".

You start hearing things about some Jason guy.  Much to your horror, you find out that Jason is not a person, but a subset of the Javascript standard, JSON (which a quick google search will lead you to it's home)

You are reassured by the home page that JSON is easy learn, and quickly get thrown into grammar parsing diagrams to demonstrate how elegant it is.  There is even a nifty comprehensive diagram on the side that tries to illustrate the grammar a different way.  Confused further?

Fear no more.  It's truly not all that scary.

JSON's website respectfully avoids saying that it's an alternative to XML as a data interchange format (ok, almost).  But that is essentially what it is.  Feel better?

Well you would if every example didn't look like a big mess of brackets, curly braces, names and numbers, right?

[{"num":1,"text":[[0,0,66,21,0,"Explain"],[0,65,33,21,0,"the"],[0,99,95,21,0,"differences"],[0,199,76,21,0,"between"],[0,279,63,21,1,"public"],[0,504,32,21,0,"and"],[0,542,68,21,5,"internal"],[0,615,55,21,0,"access"],[29,212,82,21,7,"modifiers"],[29,298,22,21,0,"on"],[29,340,40,21,0,"class"],[29,385,73,21,0,"methods."]]}]


To reiterate what the home page says, JSON is a data interchange format based on a couple of different types of structures: An ordered list of things (an array, list, etc), and things that live in that list.

When you "pretty print" the above JSON blob, it becomes a little clearer:
Lets have a little fun with Paint.Net to illustrate it further.  Square brackets [ ] indicate a collection, as shown in green in the next slide.  Since it's the first thing in the JSON blob, it's the Root element:
Inside that "Root" collection is an object, which is defined between curly braces { }.  
An object is like a class or dictionary type structure, and consists of value pairs as shown here...
and here...
So to summarize so far, this JSON blob of data is a List of objects (in this case, only 1 object is in the root list) with the properties of "num" (which is an integer value of 1), and the property "text" which is another List (notice the [ ]).  

And finally THAT list is a host to a bunch of lists of values:
Note that each item in the "text" list is a list separated by a comma.  Commas are used to delimit the elements (objects or other lists) in a list. 

As the JSON website states, these "element" structures transcend nearly every language out there.  C# is no exception.  Copy the unpretty blob of data way above my slides into your clipboard and visit the json2csharp.com website.  Here it is again so you don't have to scroll:

[{"num":1,"text":[[0,0,66,21,0,"Explain"],[0,65,33,21,0,"the"],[0,99,95,21,0,"differences"],[0,199,76,21,0,"between"],[0,279,63,21,1,"public"],[0,504,32,21,0,"and"],[0,542,68,21,5,"internal"],[0,615,55,21,0,"access"],[29,212,82,21,7,"modifiers"],[29,298,22,21,0,"on"],[29,340,40,21,0,"class"],[29,385,73,21,0,"methods."]]}]

Paste it into the box and click Generate.  Magically, a class appears that represents a host for that data:



Using some of the built in serialization attributes, we can utilize the Data Contract framework within the .Net framework to create a class that's compatible with the JSON data, but a bit more conforming to the standard .Net naming conventions for properties:

    [DataContract]
    public class JsonMetaData {
        [DataMember(Name = "num")]
        public int Number { getset; }
 
        [DataMember(Name = "text")]
        public List<List<object>> TextItems { getset; }
    }


Getting C# to serialize/translate our blob of data to this new POCO called JsonMetaData is fairly trivial.
.Net actually has a built in bi-directional helper class to move JSON data to an object, or translate a data contract object (such as the one above) to a blob of JSON data.

The DataContractJsonSerializer  lives in the System.Runtime.Serialization assembly in the .Net framework, so be sure to add that reference (by the way, the DataContract/DataMember attributes live there as well)

Lets say our blob of JSON data above lives in a text file called JsonFile.txt

We would be able to read the JSON formatted data and create a list of JsonMetaData objects from that file simply by doing this:

List<JsonMetaData> aJsonData;
var serializer=new DataContractJsonSerializer(typeof(List<JsonMetaData>));
using (FileStream aStream = new FileStream("JsonFile.txt"FileMode.Open))
{
    aJsonData = (List<JsonMetaData>)serializer.ReadObject(aStream);
}


Snooping at the aJsonData object reveals the data from the file organized into this list of objects:


Outputting the aJsonData object into a file formatted as Json is just as simple:

using(FileStream aStream=new FileStream("output.txt"FileMode.CreateNew)){
    serializer.WriteObject(aStream, aJsonData);
}
The above code writes the aJsonData object to a file called output.txt, which now looks like this:



Easy.  And not scary at all.  

I should also mention that there are other serializers for JSON out there that are better/faster/stronger than the one built into the .Net framework (such as the excellent ServiceStack.Text project).