04 January 2007

JavaScript Object Notation (JSON)

This article first appeared in the November 2006 issue of Visual Systems Journal (VSJ).

In the July/August 2006 issue of VSJ, Mike James showed the basics of how to make Asynchronous JavaScript and XML (Ajax) calls from a web page to a server using an XMLHttpRequest object. This returns either plain text in responseText or XML in responseXML properties. Unfortunately, XML can be a little cumbersome to use, which isn't going to make your JavaScript any easier to understand. However there is an alternative in the form of JavaScript Object Notation (JSON, pronounced Jason) which is a string representation of structured data using JavaScript's object literal notation, ie name/value pair objects.

Here's some XML:
<?xml version='1.0' encoding='UTF-8'?>
<name>A Bee Co</name>
<contact type='email'>sales@abee.co.uk</contact>
<employee type='Manager'>
Alison Bee
<employee type='worker'>
John Sloop

In JSON the same data might look like this:
{ "business":
{ "name": "A Bee Co",
"contact": {"type": "email", "value": "sales@abee.co.uk" },
"employee": [ {"type": "Manager", "value": "Alison Bee" },
{"type": "worker", "value": "John Sloop" }

If the above JSON string is in a var called Business, then it can be parsed very simply in JavaScript:
    var biz = eval("(" + Business + ")");

The following easy-to-use values are then available:
•  biz.business.name: A Bee Co
•  biz.business.contact.type: email
•  biz.business.employee.length: 2
•  biz.business.employee[0].value: Alison Bee
As you can see, the JSON string has been converted into an object tree. If you remove the superfluous "business" object from the JSON, then the values would be even simpler, eg biz.name.

Note that the multiple "employee" XML elements were translated into a JSON/JavaScript array. If there were just one employee, then biz.business.employee would simply be a property string. To cope with this, I use my ObjectToArray function to convert this property into an array which lets me handle it more simply:

function ObjectToArray( obj)
if( !obj) return new Array(); // zero element array
if( !obj.length) return new Array(obj); // one element array
return obj; // array already
var employees_array = ObjectToArray(biz.business.employee);

This approach works well as long as you know the structure that you are expecting, which will usually be the case. Obviously you will then want to do something with your data, ie show it to the user. Be careful if you are using server-side processing such as ASP.NET because changing a page object will not necessarily change the value seen at the next real postback, or worse, validation errors can occur. Handling interactions between client and server variables can be a messy kettle of fish which I don't want to go into here, but can be solved using Atlas and other Ajax frameworks. In next month's article I suggest a simple client-server scenario which makes use of JSON, XML, JavaScript and ASP.NET2.

Anyway, back at the bit-face, you can find out more about JSON at www.json.org. JSON supports these types of values: string, number, object, array, boolean and null. Strings are in Unicode and various escape sequences are supported. JSON doesn't support binary data so you cannot embed images. JSON seems to be supported by all versions of JavaScript in browsers.

JSON can be used in other languages apart from JavaScript. It's main use seems to be data-interchange, particularly in Ajax requests. Note that Ajax requests are not supported by older browsers. Although ease of use was the original raison d'etre for JSON, it is now also commonly used because it is more compact than XML resulting in reduced data transfer requirements.

Parsing time is also reputedly less for JSON. However you need to be careful using eval() against an untrusted source. The JSON web site provide a file json.js that includes a safer parser string method prototype parseJSON(), so replace the above eval() call with:
var biz = Business.parseJSON();

This still doesn't stop potentially dangerous values appearing as parsed values, so be careful if you stuff values into DOM innerHTML values for example. The JSON JavaScript code also defines toJSONString() to convert JavaScript objects and arrays into JSON.

C# XML to JSON conversion

In a recent web application I decided to store and process data server-side in XML because this is a standard storage type and ASP.NET2 provides good routines for handling an XmlDocument in memory. However I wanted to transfer information to the web page client in JSON, and decode returned information in JSON.

Good old www.json.org provided classes to convert JSON into C# objects at www.json.org/cs.zip. As an example, in JavaScript convert your employee array to a JSON string:

var JSON_employees = biz.business.employee.toJSONString();

Once this is safely server-side, use C# code like this to retrieve the name/value pairs for each employee, slightly laboriously:
    using Nii.JSON;
JSONArray employees = new JSONArray(JSON_employees);
for (int eno = 0; eno < employees.Count; eno++)
JSONObject jemployee = (JSONObject)employees[eno];
for (int ano = 0; ano < jemployee.Count; ano++)
string name = jemployee[ano].ToLower();
string value = jemployee[name].ToString();

I couldn't find a means of converting XML into JSON in C#, so I thought that it must be straight forward to write my own converter. It turned out that there were more XML scenarios than I had originally envisaged. For simple XML elements containing text there seems an obvious translation:
 XML: <xx>yyy</xx>
JSON: "xx":"yyy"

If the XML element has attributes or contains child elements then these are converted into object name/value pairs, with text usually converted into a field called "value". (Life gets complicated if there is an attribute or child elements called "value".)
 XML: <xx w='zzz'><aa>bb</aa>yyy</xx>
JSON: "xx": { "aa":"bb", "w":"zzz", "value":"yyy" }

Duplicate elements are converted into an array:
 XML: <xx><aa>bb</aa><aa>cc</aa></xx>
JSON: "xx": { "aa": ["bb","cc"] }

One example of "equivalent" XML and JSON online cleverly contracted this:
 XML: <employees><employee>bb</employee><employee>cc</employee></employees>
JSON: "employees": ["bb","cc"]

Note that XML and JSON conversions are not necessarily reversible, ie you cannot convert one to the other and back again and guarantee to get the same as you started.

You can get my code online www.phdcc.com/xml2json.htm. The code also makes sure that characters are escaped if necessary for correct representation in JSON.

www.json.org, www.json.org/js.html, www.json.org/cs.zip, www.crockford.com, www.phdcc.com/xml2json.htm

No comments: