
JSON, Marshall, Semantic, Serialize, YAML
Devi is creating an Ajax calendar. The browser periodically polls for new appointments, which the server is sending as JSON messages. Since JSON messages are just Javascript code for object creation, Devi's browser script only needs to run eval against each message in order to reconstruct the appointment.
Ajax apps require messages to be transmitted back and forth.
Both browser and the server must be able to access the message. That usually means the format must be easily accessed in Javascript as well as whichever server-side language is used.
Pass messages between server and browser in Javascript Object Notation (JSON) format. JSON is a standard serialisation format, created in 2002 as a cleaner and lighter alternative to XML. As with XML, the object can range in complexity from a simple string to a deep hierarchical structure. Also like XML, JSON is language-neutral, meaning that you could marshall a C++ object into JSON notation, and unmarshall it to form an object in Perl. But in practice, JSON is particularly suited to browser-server communication because it's a format based on Javascript.
In fact, a JSON Message is Javascript. This is a valid JSON Message:
"Homer J."
You can test browser-based JSON conversion on the Basic JSON Demo. As you'll see there, the JSON message "Homer J." maps to the Javascript string, Homer J..
Here's a more complex example (as on the demo, reformatted):
{"houseNumber":"742",
"street":"Evergreen Terrace",
"city":"Springfield",
"postcode":"49007",
"country":"USA",
"comments": ["Deliveries accepted.","Familiar address, huh?",""]
}
As you can see, this JSON message is just a Javascript object literal. You convert it like this:
var name = eval("(" + nameJSON + ")");
Or like this if it takes your fancy:
var name=new Function("return " + nameJSON)();
Note that you don't even need a JSON library in the browser. The browser can pick up a JSON string using an “XMLHttpRequest Call”, and simply run the standard eval function.
However, there is actually a Javascript JSON library which adds two important capabilities: (a) parse() for safer string-to-object conversion, and (b) stringify() for object-to-string conversion. The former is an alternative to manual Javascript evaluation, because evaling arbitrary messages puts your app at risk of running malicious Javascript code. Thus, the string-to-object conversion should be executed if you don't trust the message.
var name = JSON.parse(nameJSON);
If you need to upload something to the server, you'll need to convert a Javascript object to JSON with stringify(). The Basic JSON Demo shows this conversion process too. The call looks like this:
var nameJSON = JSON.stringify(name);
So far, the examples have considered only Javascript conversion. But JSON wouldn't be very useful if you could only convert to and from Javascript objects - you need to convert at the other end too, and your server-side is probably not written in Javascript. That's why there are JSON processors for many languages. Using these processors, you can easily share an object between Javascript and your favourite server-side language.
A remoting modification of the Basic JSON Demo sends JSON to the server, using “XMLHttpRequest Call”s. There, it's converted to standard PHP objects using Michael Migurski's JSON-PHP library. The library works similarly to JSON libraries for Java, .Net, and other languages. The following code converts JSON to a standard object:
$json = new JSON();
$newObject = $json->decode($jsonString);
while the following code performs the reverse operation:
$json = new JSON();
$json = $json->encode($object);
Many websites have a session timeout feature, though it's not implemented the browser-side manner described here.
Kiko is an online calendar application with a slew of Ajax features (Figure 1.24, “Kiko”). As you'd expect, the server holds a model of the calendar and the browser keeps uploading changes using “XMLHttpRequest Call”s. JSON is the message format used for server responses - each response is a list of objects.
Delicious, a social bookmarking tool, provides a “Web Service” that exposes a user's recent bookmarks in the form of a JSON Message. For reasons discussed in “On-Demand Javascript”, this means a browser script can conveniently grab the data without the need for a “Cross-Domain Proxy”.
Jim Ley's Route Planning application shows you all the routes for a given airport, and, as his long-running XMLHttpRequest Tutorial explains, it uses JSON. For example, a JSON Message for the LAX airport is available at http://jibbering.com/routeplanner/route.1?LAX. What the browser receives from an “XMLHttpRequest Call” is a JSON Message as follows ("..." has been substituted for multiple data items):
{from:'LAX',airports:[{id:"AMS",country:"NL",lat:"52.316666666667",lon:"4.7833333333333",tz:"Europe/Amsterdam",name:"Amsterdam",shortname:"Schiphol"},...,{id:"IAD",country:"US",lat:"38.95",lon:"-77.45",tz:"America/New_York",name:"Washington,
DC",shortname:"Washington Dulles International"}],routes:[{carrier:"star",toAirport:"AMS",miles:5570},...,{carrier:"oneworld",toAirport:"DCA",miles:2304}]}
Ajax.Net is one of several “Ajax Stub” frameworks that uses JSON Messages to transfer data, which can easily be converted to and from native objects at either end. For more details, see "JSON" in the Related Patterns of “Ajax Stub”.
Kiko responds to “XMLHttpRequest Call” with JSON Messages. When you log in, it downloads a list of appointments like this (reformatted below):
[
{"title":"text","isevent":"bool", "picture":"text","starttime":"timestamp","endtime":"timestamp","recurs":"int2",
"recurend":"timestamp","insystem":"timestamp","recurstart":"timestamp", "recurweek":"int2","description":"text","defaultfree":"bool","location":"text","apptid":"int8"},
{"title":"Roundup meeting","isevent":"t","picture":"","starttime":"2005-09-16 19:00:00","endtime":"2005-09-16
19:30:00","recurs":"1","recurend":"","insystem":"2005-09-12 14:52:10.965713","recurstart":"2005-09-16
04:00:00","recurweek":"16","description":"Hopefully just a quick roundup","defaultfree":"f","location":"Cyberspace","apptid":"9222"},
{"title":"Go Home!","isevent":"t","picture":"","starttime":"2005-09-15 21:00:00","endtime":"2005-09-15
21:30:00","recurs":"0","recurend":"","insystem":"2005-09-12 15:00:33.659793","recurstart":"","recurweek":"","description":"","defaultfree":"f","location":"Office,
Bar, Home","apptid":"9288"}
]
Note that the message format here is a little unusual: everything is Strings, whereas JSON can store booleans and numbers directly. Consequently, the first element of the array includes some metadata to facilitate conversion, and the Javascript includes a generic function to create native Javascript objects from JSON messages like this.
Kiko's browser script also includes some conversion to JSON, as shown below (though I was unable to exercise this code). Typically, requests in Kiko are made as POSTs with CGI-style parameters and only the responses are JSON.
var obj=json.stringify({'type':'newuser','email':email})
JSON defines itself as a "fat-free alternative to XML". Before considering the differences between the formats, let's first consider what they have in common:
Both are formats that depict an object as a plain-text string.
Being plain-text string formats, both are suitable for transfer across HTTP. This means that both are suitable as inputs and outputs for a “Web Service”.
Each format is supported by libraries in numerous languages, including Javascript. There are libraries to convert from native objects to either format and back again to native objects.
JSON has several advantages over XML:
JSON is more compact and the lack of tags sometimes leads to a better visual representation of the underlying data.
It's often claimed that JSON is faster for browsers to parse, though a recent investigation suggests XML parsing does scale better.
JSON is a concrete data format. XML, in contrast, is really a meta-format, and a developer has many choices to make about the precise XML dialect to use. Each mapping strategy has its own conventions - for example, developers need to decide on tag names and decide between tag attributes or nested tags. Consequently, a server-side XML-object mapping framework may not be message-compatible with a Javascript counterpart; and don't underestimate the amount of meetings and emails that will be necessary to resolve a seemingly trivial argument over data formats. In that sense, JSON is closer to a defined XML dialect than to XML itself.
Within the browser, JSON has the edge in terms of support and consistency, since it's based on standard Javascript.
JSON happens to be quite compatible with YAML ("YAML Ain't Markup Language"), a similar lightweight alternative to XML that's gaining traction in the dynamic scripting community.
XML has several advantages over JSON:
XML is vastly more familiar to the IT community than JSON.
XML is more self-documenting. The header identifies which XML format is being used, and there's often a schema or DTD which defines the format precisely.
XML has much more support in terms of libraries and tool support. JSON libraries tend to be simply about conversion, which its advocates would probably argue is all that's required. XML, on the other hand, has support in terms of DTD and Schema validators, XPath tools to interrogate the data, XSLT processors to perform translations, and so on. Furthermore, many IDEs, editors, and debugging environments make XML easy to work with.
For any given task, developers usually have the luxury of choosing between several competing implementations.
Being a portable object format, JSON is a useful way to facilitate calls from browser to server.
Since a JSON Message is an ordinary Javascript expression, it can be pulled in using “On-Demand Javascript”. Data from external domains can be accessed this way, as explained in “On-Demand Javascript”.