Introduction

Thanks to the increasing use and education of efficient JavaScript techniques in today’s web applications, JSON has become the data format de jour of the enterprising young web developer. JSON is particularly useful at loading state—passing and loading data that is unique to a particular client. The question we’ve run into around here, is what is the best way to get data off of our server and into a JSON object so it can be processed by the browser? Turns out, there’s a few ways to handle it and they each come with a few caveats. Today we’re going to examine four different approaches to creating a JSON object on page load (Ajax, innerHTML, Embedded Script Tags and Server Processed JavaScript) and discuss the pros and cons of each method.

Note: Some of the example code presented below uses the JSON Parser and Prototype Framework. You may need to grab yourself a copy of each if you want to follow along.

The Concept

Just to make sure we’re all on the same page, let’s do a quick rundown of why it’s important to figure out how to load a JSON object on page load. A typical web page may pull data from the server, and arrange all the data in proper XHTML markup form with only server side processing (like PHP). But on JavaScript intensive web sites (like most web applications), JavaScript may be needed or involved in the initial page load before everything is ready to play and interact with. In these cases, the data is pulled from the server, sent to JavaScript (via a JSON friendly format) where the script then places the data into the markup accordingly. Imagine the data was static, the JavaScript may look similar to this:

user = {"first":"Ryan", "last":"Campbell"} drawName(user);function drawName(user) { // modify the DOM with the information }

An object is created, and the data from that object is placed into the DOM. Unfortunately, most sites have data coming from a database and aren’t static. So how is that a user object is created? That’s what we’ll look at with the following four approaches. For each approach, we will take a look at the code required to populate the user object with the necessary data.

Ajax

Everyone’s favorite new candy. What better way to load data than with the ever popular Ajax? Well, it isn’t exactly the best approach performance-wise in my opinion, but it does have its uses depending on your development preferences. Here’s how it usually works: onload a script executes an Ajax request that queries the server for a JSON string. The server sends back the string, and the string is then converted into an object.

var myAjax = new Ajax.Request( 'url-to-server', {method: 'post', parameters: 'action=lookupUser&id=23, onComplete: function(r) { user = JSON.parse(r.responseText); } } );

Once the server sends back the response, JSON.parse() then converts our string into the actual JavaScript object. From there, we can then have JavaScript modify the DOM with the data.

While I haven’t seen this method used much in my experience, there are two definite benefits: it provides consistency and you don’t have to depend on a global variable. For an example of consistency, we can look at something like paging. When the user clicks on a “Next” link to receive something like the next 20 results from a search, the Ajax request that fires onclick is exactly the same every single time. With the Ajax method, we can also use the very same request to run onload , so that you can isolate where your data is coming from ahead of time. The important thing is to analyze the usage of common objects on the server. Also, it’s nice to know exactly where your user object is being created. As we’ll see in some of the other approaches, the user object must be initialized in a global variable.

What’s wrong with this method? Well, usually when a page loads up, the server establishes a database connection and initializes common objects. That means calling a simple function, such as lookupUser(23) , takes very little additional resources since only one extra query is being made. To call this same function through an Ajax request requires us to create a new HTTP request, a new database connection, and the re-initialization of common objects. The performance hit to me just isn’t worth it if the other methods are available.

innerHTML

The innerHTML approach relies on populating HTML elements (like a hidden div) with data from the server and them having JavaScript fetch the innerHTML of those elements onload via the very quick document.getElementById or popular $() function.

// The HTML <div id="jUser" class="hide">{"first":"Ryan", "last":"Campbell"}</div>// The JavaScript user = JSON.parse($('jUser').innerHTML);

Using innerHTML to send JSON to the client has promise, but the practical usage is limited because of it’s strike against the separation of layers. In our ideal programming environment, CSS, HTML and JavaScript are individual layers. This works out nice so that designers can make changes without having to look at code, and developers can make changes without considering CSS. While you could think of JSON as just content and therefore justify to yourself that it does have its place in the markup, it’s a bit of a stretch.

Let’s examine if the JSON object is describing the appearance or layout of the page. The following code tells the JavaScript what type of user is being loaded. After the JSON is read by the JavaScript, the JavaScript could then add/remove markup accordingly.

{"first":"Ryan", "last":"Campbell", "rank":"Admin", "country":"United States", "template":"header"}

Given the JSON, the JavaScript could display a different, customized header for each type of user . Also, the designer can go in and change the fairly human readable string without having to open a JavaScript file, which will then change the appearance of the page. Another benefit of this method is, like the Ajax approach, it removes dependencies on global variables. They share the same weakness as well in the fact that a JSON parser is needed to read the string.

One major hassle with the innerHTML approach is escaping in JSON strings. Escaping an actual JSON object in JavaScript is weird enough, but then trying to escape an HTML string that will be parsed into JSON seems to multiply the confusion. Here is an example of escaping a link in JavaScript:

obj = {"item":"<a href=\"particletree.com\">link</a>"};

If we were to place that same code into the HTML, the parser would break. If the tags are replaced with < and > it will work, but they would have to be converted back to tags on the JavaScript side. Overall, it leads to some serious code ugliness.

Embedded Script Tags

Instead of putting a JSON formatted string into the markup, we can instead place an actual JSON object with an embedded script tag. Similar to the innerHTML approach, the server will load up the content in the flow of the markup. This time, though, it will print out script tags containing the information instead of placing it inside of an element.

<script type="text/javascript"> <!-- user = {"first":"Ryan", "last":"Campbell"} --> </script>

With this, any other JavaScript file can reference our global user object. Other than the reliance on a global variable, this method is fairly rock solid. Since JSON is native to JavaScript, no outside library or parser is needed. While the speed increases are actually minimal, it is still pretty good practice to trim down code when possible. It also creates a healthy dose of separation. Even though the JSON is still in the HTML file, it is in a separate script section and can still be easily configured. Finally, all character escaping is based off of JavaScript rules rather than a quirky combination of HTML and JavaScript.

Server Processed JavaScript

This approach is identical in concept to embedded script tags, but it takes things a step further. By setting up the server to process JavaScript as PHP (or any desired server language), we can include PHP processed strings right in the JavaScript. If we process js files as PHP (with a little htaccess tweaking), the following code would still produce valid JavaScript:

user = <?php lookupUser(23); ?>;

The code above will execute with the rest of the server code, and will ultimately output:

user = {"first":"Ryan", "last":"Campbell"}

Like embedded script tags, a global user object is created, but this time, the object is actually created in the JavaScript file, and not on the HTML page. This allows for complete separation. By including the JavaScript file in the HTML page, everything just works regardless of what is on the HTML page. It’s also nice to know that all resources needed by the JavaScript file are located within the JavaScript file. This makes everything easier to track, and reduces confusion when you’re trying debug.

As always, nothing is perfect. While this method is great in plug and play reusability, it makes caching the JavaScript file an impossibility and turns out to be limited in catch all circumstances. For example, we have a global JavaScript file on every page using this technique. However, we don’t want the JavaScript to execute on every page. For the three other methods, we can just place code to catch it:

if(user) doSomething();

By excluding the JSON, you prevent something from happening. In this case, the user object will always be created. Now, on the PHP level a check could be made to make the user object null in certain circumstances, but that leads to inevitable complications. It is much easier to just not include something in the innerHTML div or between our embedded script tags.

Which to Choose

I have used all four of these methods in projects, and they all get the job done. For most smaller scale operations, any of these will work and you won’t have to think twice about it. Personally, I find embedded script tags to be superior because they allow for flexibility, don’t require custom server configurations, and are native to JavaScript. And I try to stay away from the Ajax version the most mainly because the hits to the server really aren’t worth it when there are satisfactory alternatives available. The key is to pick one method and stick with it as often as possible for the sake of consistency.