What is JSON?
Why would we choose JSON over say XML? The key advantage of using JSON is efficiency. JSON is less verbose and cluttered, resulting in fewer bytes and a faster parse process. This allows us to process more messages sent as JSON than as XML. Moreover, JSON has a very efficient and natural object representation leading to formats such as BSON, where JSON-like objects are stored in a binary format.JSON stands for JavaScript Object Notation. In simple terms JSON is a way of formatting data for, e.g., transmitting it over a network. In this article we will look at loading JSON data using an HTTP GET request (we can also use other verbs, such as POST).
Now let’s see how jQuery can help us load JSON-encoded data from a remote source. For the impatient among you, there’s a demo towards the end of the article.
JSON jQuery Syntax
The $.getJSON()
method is a handy helper for working with JSON directly if you don’t require much extra configuration. Essentially, it boils down to the more general $.ajax() helper, with the right options being used implicitly. The method signature is:
$.getJSON(url, data, success);
Besides the required URL parameter we can pass in two optional parameters. One represents the data to send to the server, the other one a callback to trigger in case of a successful response.
So the three parameters correspond to:
- The
url
parameter is a string containing the URL to which the request is sent. - The optional
data
parameter is either an object or a string that is sent to the server with the request. - The optional
success(data, textStatus, jqXHR)
parameter is a callback function executed only if the request succeeds.
In the simplest scenario we only care about the returned object. In this case, a potential success
callback would look like this:
function success(data) {
// do something with data, which is an object
}
As mentioned, the same request can be triggered with the more verbose $.ajax()
call. Here we would use:
$.ajax({
dataType: 'json',
url: url,
data: data,
success: success
});
Let’s see this in practice using a little demo.
A Sample Application
We will start a local server that serves a static JSON file. The object represented by this file will be fetched and processed by our JavaScript code. For the purposes of our demo we’ll use Node.js to provide the server (although any server will do). This means we’ll need the following three things:
- A working installation of Node.js.
- The node package manager (npm).
- A global installation of the http-server package.
The first two points are platform-dependent. If you need some help getting either of them set up, you might want to check out our tutorial: A Beginner’s Guide to npm — the Node Package Manager, orNode’s download page (npm comes bundled with Node).
The third point can be achieved by running the following from your terminal:
npm install http-server -g
If you find yourself needing a sudo
prefix (-nix systems) or an elevated command prompt to perform this global installation, you should consider changing the location of global packages.
Once these requirements are met we can put the following three files in a new folder:
example.js
is the JavaScript file to request the data.example.json
is the example JSON file to represent our object.index.html
is the HTML page to call the JavaScript and display the data.
From the command prompt we can simply invoke http-server
within the new folder. Now http://localhost:8080 should be running the demo.
The Sample JavaScript
The following code is the complete client-side logic. It waits for the DOMContentLoaded
loaded event before attaching an event handler to the click
event of the element with the ID get-data
. When this element is clicked we attempt to load the JSON from the server using $.getJSON()
, before processing the response and displaying it on the screen.
$(document).ready(function () {
$('#get-data').click(function () {
var showData = $('#show-data');
$.getJSON('example.json', function (data) {
console.log(data);
var items = data.items.map(function (item) {
return item.key + ': ' + item.value;
});
showData.empty();
if (items.length) {
var content = '<li>' + items.join('</li><li>') + '</li>';
var list = $('<ul />').html(content);
showData.append(list);
}
});
showData.text('Loading the JSON file.');
});
});
Besides converting parts of the object to an unordered list, the full object is also printed in the browser’s debugging console. The output is generated in the <div>
element with the ID show-data
. Even though the element is being reset for every request, we only fill it if the resulting JSON object contains any items at all. Of course, for our example the data is fixed, however, in general any kind of response is possible.
Note that we also set some text for the output <div>
. If we insert some (artificial) delay for the JSON retrieval, we will see that this actually executes before any result of the JSON is displayed. The reason is simple: By default $.getJSON
is non-blocking, i.e., async. Therefore, the callback will be executed at some (unknown) later point in time.
Distilling the source to obtain the crucial information yields the following block:
$('#get-data').click(function () {
$.getJSON('example.json', function (data) {
console.log(data);
});
});
Here we only wire the link to trigger the start of the $.getJSON
helper before printing the returned object in the debugging console.
The Sample JSON
The sample JSON file is much larger than the subset we care about. Nevertheless, the sample has been constructed in such a way, to show most of the JSON grammar. The file reads:
{
"items": [
{
"key": "First",
"value": 100
},{
"key": "Second",
"value": false
},{
"key": "Last",
"value": "Mixed"
}
],
"obj": {
"number": 1.2345e-6,
"enabled": true
},
"message": "Strings have to be in double-quotes."
}
In the sample JavaScript, we are only using the array associated with the items
key. In contrast to ordinary JavaScript, JSON requires us to place keys in double-quotes. Additionally, we cannot use trailing commas for specifying objects or arrays. However, as with ordinary JavaScript arrays, we areallowed to insert objects of different types.
The Sample Webpage
We already looked at the script and the sample JSON file. All that’s left is the webpage which provides the parts being used by the JavaScript file to trigger and display the JSON file.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Request JSON Test</title>
</head>
<body>
<a href="#" id="get-data">Get JSON data</a>
<div id="show-data"></div>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="example.js"></script>
</body>
</html>
There is not much to say here. We use the minified version of jQuery (in the old version 1.9.1, which is certainly sufficient for our purposes) from the official webpage. Then we include our script, which is responsible for injecting the logic.
Note: As we are including our JavaScript files in the correct place (just before the closing </body>
tag), it no longer becomes necessary to use a $(document).ready()
callback, because at this point, the document will be ready by definition.
Demo
And this is what we end up with.
The More General Method
As already mentioned, the $.ajax
method is the real deal for any (not only JSON related) web request. This method allows us to explicitly set all the options we care about. We can adjust async
to true
if we want this to call to run concurrently, i.e., the run potentially at the same time as other code. Setting it to false
will prevent other code from running while the download is in progress.
$.ajax({
type: 'GET',
url: filename,
data: data,
async: false,
beforeSend: function (xhr) {
if (xhr && xhr.overrideMimeType) {
xhr.overrideMimeType('application/json;charset=utf-8');
}
},
dataType: 'json',
success: function (data) {
//Do stuff with the JSON data
}
});
The overrideMimeType
method (which overrides the MIME type returned by the server) is only called for demonstration purposes. Generally, jQuery is smart enough to adjust the MIME-type according to the used data type.
Before we go on to introduce the concept of JSON validation let’s have short look at a more realistic example. Usually, we will not request a static JSON file, but will load JSON which is generated dynamically (for example as the result of calling an API). The JSON generation is dependent on some parameter(s), which have to be supplied beforehand.
var url = 'https://api.github.com/v1/...';
var data = {
q: 'search',
text: 'my text'
};
$.getJSON(url, data, function (data, status) {
if (status === 200) {
//Do stuff with the JSON data
}
});
Here we check the status to ensure that the result is indeed the object returned from a successfulrequest and not some object containing an error message. The exact status code is API-dependent, however, for most GET requests a status code of 200 is usual.
The data is supplied in form of an object, which leaves the task of creating the query string (or transmitting the request body) up to jQuery. This is the best and most reliable option.
JSON Validation
We should not forget to validate our JSON data! There is an online JSON Validator tool called JSONLint, which can be used to validate JSON files. Unlike JavaScript, JSON is very strict and does not have tolerances, e.g. the aforementioned trailing commas or multiple ways of writing keys (with /
, without quotes).
So, let’s discuss some of the most common errors when dealing with JSON.
Common $.getJSON Errors
- Silent failures on
$.getJSON
calls: This might happen if, e.g.,jsoncallback=json1234
has been used, while the functionjson1234()
does not exist. In such cases the$.getJSON
will silently error. We should therefore always usejsoncallback=?
to let jQuery automatically handle the initial callback. - In the best case real JSON (instead of JSONP) is used (either by talking with our own server or via CORS). This eliminates a set of errors potentially introduced by using JSONP. The crucial question is: Does the server / API support JSONP? Are there any restrictions on using JSONP?
Uncaught syntax error: Unexpected token
(in Chrome) orinvalid label
(in Firefox). The latter can be fixed by passing the JSON data to the JavaScript callback. In general, however, this is a strong indicator that the JSON is malformed. Consider using JSONLint as advised above.
The big question is now: How do we detect if the error actually lies in the transported JSON?
How to fix JSON Errors
There are three essential points that should be covered before starting any JSON-related debugging:
- We have to make sure that the JSON returned by the server is in the correct format with the correct MIME-type being used.
- We can try to use $.get instead of
$.getJSON
as it might be that our server returns invalid JSON. Also ifJSON.parse()
fails on the returned text we immediately know that the JSON is to blame. - We can check the data that is being returned by logging it to the console. This should then be the input for further investigations.
Debugging should then commence with the previously mentioned JSONLint tool.
Conclusion
JSON is the de-facto standard format for exchanging text data. jQuery’s $.getJSON()
method gives us a nice little helper to deal with almost any scenario involving a request for JSON formatted data. In this article we investigated some methods and possiblities that come with this handy helper.
Are there any other best practices for $.getJSON()
you cannot live without?