J is for.. JSON

J

No, not the Greek hero who scored the Golden Fleece; this JSON (note – there’s no ‘a’ here) stands for JavaScript Object Notation.   JSON is quite simply a serialization format for data that leverages JavaScript as the encoding mechanism.  With JSON you can encode data structures and arrays as simple strings (that happen to be valid JavaScript syntax) and pass the strings between applications and services. 

Technically, it’s a language-independent mechanism; after all, it’s just a string much like XML is just a string.  However, given the ties to JavaScript and the ability to quickly instantiate (or hydrate) the string representation into a complex object that can be manipulated in the browser’s Document Object Model (DOM), JSON is a favorite interchange format for browser-based AJAX (Asynchronous JavaScript and XML) applications. 

The JSON format is formally described in RFC 4627 and was based on the ECMAScript Language Specification.   It’s an exceptionally light weight representation, whose primary facets are pretty much captured by the following list:

  • simple data types
    • string
    • number (decimal and exponential notation)
    • boolean
    • literals (namely, null, true, and false)
  • structure types
    • object (delmited by { })
    • arrays (delimted by [ ] )
  • MIME type: application/json
  • Unicode with UTF-8 as default encoding

So for instance, the following is JSON for an object with two string fields representing my name:

{"firstname" : "Jim", "lastname" : "O’Neil" }

and here’s one with a bit more information for one of our favorite moms:

 {
     "firstName": "Carol",
     "lastName": "Brady",
     "address": {
         "street": "4222 Clinton Avenue",
         "city": "Santa Monica",
         "state": "CA",
         "postalCode": 90401
     },
     "children": [
         "Cindy",
         "Bobby",
         "Jan",
         "Peter",
         "Marcia",
         "Greg"
    ]
 }

If I use the shorter example in an HTML/JavaScript page like this:

    1:  <HTML>
    2:  <BODY>
    3:     <SCRIPT type="text/javascript">
    4:       function showName(jsonString)
    5:       {
    6:          jsonString = '{ \"firstname\" : \"Jim\",' +
    7:                       '  \"lastname\" : \"O\'Neil\" }';
    8:          var f = eval("(" + jsonString + ")");
    9:          alert(f.firstname + " " + f.lastname);
   10:       }
   11:      </SCRIPT>
   12:      <INPUT Type="Button" onclick="showName();" Value="Who am I?" />
   13:  </BODY>
  

the result is a simple page, with a button, that when clicked yields the alert box you see here:

Who am I?

Note that the magic here is on Line 8.  The built-in eval function accepts a string containing JavaScript and just evaluates it – whatever it happens to be. 

Of course, we’re not going to be hard-coding strings in real applications, but rather interacting with user input and on-line services that pass data back and forth in JSON notation, and that brings up the question of security.  If the eval method takes any old JavaScript string, what’s to prevent something like this? 

 <HTML>
 <BODY>
    <SCRIPT type="text/javascript">
      function showName(jsonString)
      {
         jsonString = 'alert("You have been invaded")';
         var f = eval("(" + jsonString + ")");
         alert(f.firstname + " " + f.lastname);
      }
     </SCRIPT>
     <INPUT Type="Button" onclick="showName();" Value="Who am I?" />
 </BODY>

I've been hacked!

Per the RFC, you can easily prevent these types of attacks via a regular expression (involving some string substitution):

 var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
             text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
         eval('(' + text + ')')

Unless you’re a Ph.D. in regular expressions, though, that strikes me as a bit obtuse, not to mention error-prone and a maintenance nightmare.  As an alternative, you might consider some of the following options in lieu of direct use of the built-in eval function:

One of the areas I’ve been running into JSON frequently is with ADO.NET Data Services (formerly called “Astoria”).  In a nutshell, ADO.NET Data Services allows you to expose a data model (using Entity Framework) to provide the underlying model data (often a SQL Server database) as a WCF service to REST and SOAP clients.  With the REST approach, accessing data is as simple as typing a URL into a browser (which initiates a GET HTTP message to the service).

With ADO.NET Data Services, the default format is AtomPub, so if I browse to a bit of data exposed by my service: https://localhost:27339/roster.svc/Classes, I get output that looks like the following.  ADO.NET Data Services and Atom

I’d likely be using ADO.NET Client classes or other mechanism to parse the XML and make use of the data, which as you can see includes the name, description, and level of a Golfing course.

Now I can get a JSON representation of this as well, but not directly through the browser, since I need to provide an HTTP header (Accept: application/json) to request that the data come back in JSON format.  An easy way to demonstrate this is via Fiddler, which will allow me to construct the appropriate request.  So now my data comes back looking like:

 { "d" : [
{
"__metadata": {
"uri": "https://127.0.0.1:27339/roster.svc/Classes(3)", 
"type": "RecordsModel.Class"
}, "ID": 3, "Subject": "Golf", 
"Name": "Golfing For Dummies", 
"Description": "You know who you are", 
"Level": 100, "Version": "AAAAAAAAB+Y=", "ClassRegistrations": {
"__deferred": {
"uri": "https://127.0.0.1:27339/roster.svc/Classes(3)/ClassRegistrations"
}…

Note here how the JSON object is wrapped by another object with a single element, d.  That element is used to thwart an exploit that can leave your data at the hands of evil doers (check out Phil Haack’s great explanation of how it can happen).  Another thing you might have noticed are a couple of elements preceded by the underscores, like __metadata and __deferred.  While they don’t refer to data that you might be interested in per se, they are part of the ADO.NET Data Services Framework that help support lazy loading and object tracking on the client – but that’s another topic for another time!