Speed Up Your AJAX-based Apps with JSON

SON stands for JavaScript Object Notation and is a lightweight data-interchange format. Because it is text-based it is easy for humans to read and write, and it has a regular syntax that’s easy to parse programmatically. JSON is basically a subset of JavaScript and, as you’ll see, is even easier to parse than XML.

AJAX stands for Asynchronous JavaScript and XML. It’s a Web development technique used to make non-blocking calls to the server using JavaScript. The “and XML” part is likely to fade away as the time goes by. Even though AJAX initially used XML as the format for transferring data, any format will work, including HTML, plain text and?why not?JSON. After all, from a machine viewpoint XML, HTML and JSON are all plain text!

In this article you’ll see how to develop a news ticker using AJAX, JSON, JavaScript and PHP. Figure 1 should clarify the intent of the application.

 
Figure 1. News Ticker in action: The image doesn’t pay off since the scrolling feature is not visible.

If you don’t know PHP and are more familiar with another server-side technology such as ASP.NET or J2EE, don’t worry; the techniques apply to these technologies/languages as well, and you’ll find it will be very easy to translate the PHP script into another language.

Furthermore, by developing the sample app, you’ll see how to implement the Observer Pattern in JavaScript.

JSON vs. XML
JSON and XML are basically used for the same purpose?to represent and interchange data. I’ll try to show you why you might want to use JSON rather than XML in an AJAX context by showing you an example of how an employee class (actually, a list of employees) might be represented, first in XML. and then in JSON. This side-by-side comparison should let you begin to understand how to represent data in JSON. Here’s the XML version:

XML Version JSON Version
                     Lacava         Alessandro         Milan         Italy         IT                              Brown         John         Rome         Italy         IT         

   {      "employees" :      [        {          "surname" : "Lacava",          "name" : "Alessandro",          "city" : "Milan",          "state" : "Italy",           "department" : "IT"        },        {          "surname" : "Brown",          "name" : "John",          "city" : "Rome",          "state" : "Italy",           "department" : "IT"        }      ]   }

As you can see JSON is less verbose than XML, which translates directly to improved performance?less data means fewer bytes to transfer and parse, in other words JSON requires less bandwidth and fewer memory and CPU resources. JavaScript developers know that JSON is a subset of JavaScript. Indeed, the JSON code you just saw is a literal representation of arrays and objects in JavaScript!

Arrays and Objects: the JSON Fundamental Pillars
Basically, you use JSON to represent arrays and objects. In this context, by “object” I mean an unordered set of name/value pairs. For example, the object person can be represented as follows:

   { "person" :       {         "firstName" : "John",         "lastName" : "Brown",         "age" : 30,         "sex" : "M"      }   }

Curly brackets ({ }) delimit objects in JSON. Each object begins with { and ends with }. In this case, person is the name of the object, followed by a list of the object’s properties expressed as name/value pairs. In the preceding example the properties are: firstName, secondName, age, and sex. The value of a property can be one of the following types: string, number, object, array, true, false, or null. The example above uses three strings and one number?the age.

On the other hand, an array is an ordered set of values, where the values can be any of the types already mentioned. Here’s an example of an array in JSON:

   {"states" :      [        "California",         "Florida",         "Alabama"     ]   }

At the beginning of this article I stated that JSON is a subset of JavaScript?that is, JSON text is nothing more than a literal representation of JavaScript objects and arrays. If you’re not a JavaScript expert and still don’t believe me, I’m going to demonstrate that. Let’s get back to the representation of an object. In JavaScript, you could define a person object like this:

   var person = new Object();   person.firstName = "John";   person.lastName = "Brown";   person.age = 30;   person.sex = "M";

Or, using the literal notation:

   var person =    {      "firstName" : "John",      "lastName" : "Brown",      "age" : 30,      "sex" : "M"   };

At which point you might object that, even if this last version looks like the JSON syntax, it is still not the same. Well, you’re right, but look at the following code:

   var obj = eval(      {"person" :         {           "firstName" : "John",           "lastName" : "Brown",           "age" : 30,           "sex" : "M"        }      }   );      //display a popup with the person's first name.   alert(obj.person.firstName);

Now I bet you are convinced that JSON is nothing more than a subset of JavaScript. The eval built-in JavaScript function is a real JavaScript interpreter and can be used to execute any JavaScript code. Yes, that’s right! It takes just one single line of code to parse a JSON message. At this point, those of you?well, us?that used JavaScript to parse XML, are really appreciating JSON. However I don’t want to discredit XML. It is and remains a great data-interchange format. It’s a “must-have” format to let two different technologies talk transparently. But, in this case, JavaScript and JSON are not two different technologies! Actually they speak the same language (JavaScript) so why use an “interpreter” to let them communicate?

Using JSON with AJAX
Since JSON is JavaScript and AJAX is JavaScript couldn’t we use them together to build brilliant Web 2.0 applications? The answer is yes, of course. As a sample app I developed a news ticker. Figure 2 shows the architecture of the sample application.

 
Figure 2. News Ticker architecture: You should always try to separate data access, business logic and presentation layer.
 
Figure 3. Observer Pattern: The Observer pattern is one of the most commonly-used design patterns.

At the beginning of this article I said I was going to use the Observer Pattern to implement the sample application. Figure 3 shows a class diagram that represents a simplified version of this very useful pattern.

The Observer Pattern
The Observer Pattern defines a one-to-many dependency between objects so that when one object (the Observee) changes state, all its dependents (the Observers) are notified and updated automatically. Most literature refers to the Observee as the Subject. For this article I’ve used the term “Observee” to emphasize the role of this object?it’s the object responsible for downloading the news. The Observers are the objects interested in receiving the news.

The sample application implements the Observer using a JavaScript class called “Marquee,” while the Subject (from now on I’ll refer to it as Observee) is the “ContentRetriever” class. Note that, Marquee and ContentRetriever both represent the concrete classes of Figure 3. They do not inherit from abstract classes because JavaScript doesn’t strictly define abstract classes, a subject which?even if we could “simulate” abstract classes?goes beyond the scope of this article. Marquee’s responsibility is to display the information within a marquee element. ContentRetriever, on the other hand, takes care of downloading the news in JSON format, using AJAX calls.

ContentRetriever use a helper class, HtmlBuilder, to parse the retrieved JSON text and build the HTML code to be displayed within a marquee HTML element. This helper class isolates the presentation logic. If you wanted to change the news format you would need to modify only the logic in HtmlBuilder. The sample application uses a CSS stylesheet to define the fonts, colors and so on, which you can modify it according to your taste.

Here’s the ContentRetriever class constructor:

   function ContentRetriever(jsonDataRetriever, observerObjectsArray)   {      // JSON data retrieved and parsed      this.jsonData = "";      // URL of the Server-side component responsible       // for retrieving the JSON data      this.jsonDataRetriever = jsonDataRetriever;      // AJAX object      this.ajaxObj = createHttpRequest();      // array of observers      this.observerObjectsArray = observerObjectsArray;   } 

The first parameter is a URL that points to the server-side component responsible for retrieving the news. The second parameter is an array of objects (observers) interested in being notified when the information gets retrieved by ContentRetriever (the observee). After all, this is the essence of the Observer Pattern: something doing a job and others just sitting around waiting to be notified when it’s done! The function createHttpRequest creates an XMLHttpRequest object, taking browser differences into account. This function is defined within the ajax.js file that you can find in the downloadable code for this article. The file demo.htm contains the JavaScript code that builds and displays the ticker:

   

The preceding code creates an instance of the Marquee class, which I’ll discuss shortly, and then builds a ContentRetriever object, passing in both the URL of the PHP script responsible for retrieving the data and an array of observer objects?in this case just one.

Here’s the code of the Marquee constructor:

   function Marquee(elemId, scrollamount, stopOnMouseOver)   {      this.elemId = elemId;       this.scrollamount = scrollamount;       this.stopOnMouseOver = stopOnMouseOver;         this.dataArray = [];      this.errorMessage = "No news available";   }

The Marquee constructor takes three parameters:

  • elemId?This is the id of the div element apt to display the news.
  • scrollamount?The scrollamount attribute of the marquee HTML element. It indicates the scrolling speed.
  • stopOnMouseOver?A Boolean indicating whether news scrolling should be stopped when the user hovers the mouse over a news item.

The dataArray property is the array containing the news items retrieved and parsed, and the errorMessage property is an error message to display if the news download fails.

The method that actually retrieves the news is getContent(), in the ContentRetriever class. Here’s the code:

   ContentRetriever.prototype.getContent = function()   {      if (this.ajaxObj)      {         var instance = this;         this.ajaxObj.open('GET', this.jsonDataRetriever, true);         //callback function         this.ajaxObj.onreadystatechange =             function(){instance.processDataRetrieved();};         this.ajaxObj.send(null);      }   };

First getContent() checks whether the XMLHttpRequest object was created correctly. Then it prepares an AJAX call using the HTTP GET method, the URL for the PHP news-retrieval script, and a Boolean specifying whether the call should be asynchronous (the third parameter (true) of the open() call). Because the call is asynchronous you must define a callback function that will execute when the call completes; in this case, that’s processDataRetrieved. Lastly it sends the AJAX call without any other data (using null as the argument of send()).

The server-side script that retrieves the actual data?the file tickerDataRetriever.php?is very simple:

   

For simplicity’s sake, the news in JSON format was hard-coded within a text file. Of course, in a real world application, the information would be retrieved from a database, an RSS feed or whatever you might choose for dynamic content. In this case, the PHP script just retrieves the JSON text and passes it back to ContentRetriever. This is the content of news.txt:

   {      "items" :       [         {             "title" : "This is the first item's title",            "link" : "http://www.alessandrolacava.com",            "description" : "This is the description of the "first" news.                The link takes you to my Web site"         },         {             "title" : "Second item's title",            "link" : "http://www.json.org",            "description" : "You can appreciate how easily you                can parse JSON text. This link takes you to the JSON Web site"         },         {             "title" : "This is the third item's title.",            "link" : "http://www.devx.com",            "description" :                "The link for this item takes you to the DevX Web site"         }      ]   }

As you can see, the file content is just a JSON string representing an array of objects. Each object represents a news item and has three properties: title, link and description. Notice the escaped double quotes () in the first item’s description value. You must escape embedded double quotes; otherwise the parser will interpret them as the end of the field value. At the end of the article you’ll see how to automate this process when retrieving dynamic content.

The following function processes the retrieved content (the JSON text):

   ContentRetriever.prototype.processDataRetrieved = function()   {      //request completed      if (this.ajaxObj.readyState == 4)      {          //request succeeded         if (this.ajaxObj.status==200)         {             //check whether the response is empty            if(this.ajaxObj.responseText != null &&                this.ajaxObj.responseText.length > 0)            {               var htmlBuilder = new HtmlBuilder(this.ajaxObj.responseText);               //parse the JSON data               this.jsonData = htmlBuilder.getHtml();            }            else            {               //return a zero-length array if an error occurs               this.jsonData = [];            }            // notify observers            this.notify();               }      }   };

The preceding code first checks if the request completed successfully. Then it instantiates an HtmlBuilder object, passing in the JSON text. The HtmlBuilder’s getHtml method parses the JSON string and builds the HTML code to be displayed within the marquee. When it’s done, it calls the notify method:

   //notify all observers   ContentRetriever.prototype.notify = function()   {      //call the observers' callback function, passing in the resulting array      for(var i = 0; i < this.observerObjectsArray.length; i++)      {         this.observerObjectsArray[i].update(this.jsonData);      }   };

The notify method calls the update method of all the subscribed observers?in this case just one, the marquee.

The HtmlBuilder getHtml function does the transformation work of creating HTML from the returned JSON code:

   //build the HTML code and return it as a JavaScript array of items   HtmlBuilder.prototype.getHtml = function()   {      var ret = [];      //decode the JSON text      var obj = this.decodeJson();      //get the array      var items = obj.items;      //build the HTML code using the array      for(var i = 0; i < items.length; i++)      {         var item = "";         //build the title         item += this.buildTitle(items[i]);         item += "
"; //build the description item += this.buildDescription(items[i]); item += "
"; ret.push(item); } return ret; };

This function parses the JSON text and creates a set of HTML strings that it returns to ContentRetriever as a JavaScript array. The actual parsing of the JSON string occurs within the decodeJson function:

   HtmlBuilder.prototype.decodeJson = function()   {      return eval("(" + this.jsonString + ")");   };

As you can see it takes just one line of code to parse the whole JSON data! Isn't that great? If you think it's not then, as an exercise, represent the same news using XML and parse it using JavaScript. I bet you'll change your mind at once!

The rest of getHtml just formats the news conveniently and creates an array of news items. This array is the parameter passed to the update method of Marquee that displays the news within a marquee HTML element.

Security Concerns and JSON Support in Other Languages
You've seen that parsing a JSON string is as simple as using the eval function. The problem with this function is that it executes any JavaScript code! This can be potentially dangerous if you're not sure where the data comes from, and is particularly dangerous when it comes from third parties and not from the same Web server. In such cases you should use a JSON parser rather than the built-in JavaScript eval command. A JSON parser accepts only JSON text (not any JavaScript) so it is much safer. Obtaining a JSON parser is simple for most languages. The official JSON Web site offers APIs for most languages, including PHP, Java and C# that you can use to parse JSON text without difficulty, with one or two lines of code. To parse JSON text safely on the client-side, you can use this open-source JavaScript implementation of a JSON parser. Even when you add a separate parser, the process stays very simple. Indeed, to encode and decode JSON text you just need a couple of lines of code.

For example, to convert from JSON text into JavaScript code you use the parseJSON method:

   var myObject = myJSONtext.parseJSON();

And to serialize a JavaScript data structure into JSON text you use the toJSONString method:

   var myJSONText = myObject.toJSONString();

The latter function also takes care of escaping double quotes and other embedded special characters during the conversion.

In this article you've seen how JSON can simplify the code of your AJAX Web applications. The sample app showed how you can develop a highly-customizable news ticker that implements the Observer Pattern in JavaScript. This pattern lets you extend the application easily. For example, you could create another observer component that displays the news items using a time interval. To do that, you would just need to create another JavaScript class and add the logic to its update method that receives a JavaScript array representing the news. Then you can add this new observer object to the observee, ContentRetriever. One way would be by passing it to the ContentRetriever's constructor:

   var marquee = new Marquee(...);   var newTicker = new NewTicker(...);   var contentRetriever = new ContentRetriever("./tickerDataRetriever.php", [marquee, newTicker]);   ...   contentRetriever.getContent();

Another way would be to add the observer using the ContentRetriever's attach method:

   var marquee = new Marquee(...);   var contentRetriever = new ContentRetriever("./tickerDataRetriever.php", [marquee]);   ...   var newTicker = new NewTicker(...);   contentRetriever.attach(newTicker);   ...   contentRetriever.getContent();

Running the Sample Code
This article touched many areas (JSON, AJAX, JavaScript, Observer Pattern, CSS), making it impossible to examine each and every line of code thoroughly. However, you can freely download the fully-commented code for this article and inspect the remaining code yourself. One last note. The PHP code for this article needs to be run on a Web server?Apache HTTP Server will do. If, for example, you put the code within the Ticker folder you would call it using a similar URL:

   http://localhost/Ticker/demo.htm

Of course you will need to change the preceding URL to match your environment.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: