Reading and writing JSON in JavaScript
JSON originated as a means to carry data between web servers and JavaScript, so let's begin with a simple code snippet that reads and writes JSON in JavaScript in a web browser. We'll show the entirety of a web application using AJAX and JSON in Chapter 4, Using JSON in AJAX Applications with jQuery and AngularJS; what follows is how to obtain a JavaScript object from JSON and how to create a JSON string from a JavaScript object.
Getting ready
You'll need a way to edit the JavaScript and run it in your browser. In this example, and nearly all examples in this book, we'll use Google Chrome for this. You can download Google Chrome at https://www.google.com/chrome/browser. Once you install Google Chrome, you'll want to activate the JavaScript console by clicking on the Customize and control Doodle Chrome icon on the right-hand side, which looks like this:
Then, you'll want to go to More Tools | JavaScript console. You should see a JavaScript console on the side of the web page, like this:
If you prefer key commands, you can also use Ctrl + Shift + J on Windows and Linux, or control + option + J on a Macintosh.
From here, you can enter JavaScript on the lower right-hand corner and press Enter (return on a Mac OS X system) to evaluate the JavaScript.
How to do it...
Modern web browsers, such as Chrome, define a JSON object in the JavaScript runtime that can convert the string data containing JSON to JavaScript objects, and convert a JavaScript object to JSON. Here's a simple example:
>var json = '{"call":"KF6GPE","type":"l","time": "1399371514","lasttime":"1418597513","lat":37.17667,"lng": -122.14650,"result" : "ok" }'; <- "{ "call":"KF6GPE","type":"l","time":"1399371514", "lasttime":"1418597513","lat":37.17667,"lng":-122.14650, "result" : "ok" }" >var object = JSON.parse(json); <- Object {call:"KF6GPE",type:"l",time:"1399371514", lasttime:"1418597513",lat:37.17667, lng:-122.14650,result: "ok"} > object.result <- "ok" >var newJson = JSON.stringify(object); <- "{ "call":"KF6GPE","type":"l","time":"1399371514", "lasttime":"1418597513","lat": 37.17667,"lng": -122.14650, "result" : "ok" }"
Note
In this and subsequent JavaScript examples, the text you type in the JavaScript console is preceded by a >
symbol, while what the JavaScript console prints is anything beginning with <-
symbol.
How it works...
Chrome and other modern web browsers define the JSON
object, which has methods to convert between strings containing JSON and JavaScript objects.
In the previous example, we begin by setting the value of the json
variable to a simple JSON expression consisting of one attribute result
with the value ok
. The JavaScript interpreter returns the resulting value of the variable json
.
The next line uses the JSON
method parse
to convert the JSON string referenced by json
into a JavaScript object:
>var object = JSON.parse(json); <- Object { call:"KF6GPE", type:"l", time:"1399371514", lasttime:"1418597513", lat:37.17667, lng:-122.14650, result: "ok"}
You can then access any of the values in the object, just as you would any other JavaScript object; it is, after all, just an object:
> object.result; <- "ok"
Finally, if you need to convert an object to JSON, you can do that with the JSON
method stringify
:
>var newJson = JSON.stringify(object); <- "{ "call":"KF6GPE","type":"l","time":"1399371514", "lasttime":"1418597513","lat": 37.17667,"lng": -122.14650, "result" : "ok" }"
There's more...
You should know two things about these methods. First of all, parse will throw an exception if the JSON you pass is malformed, or isn't JSON at all:
>JSON.parse('{"result" = "ok" }') <- VM465:2 Uncaught SyntaxError: Unexpected token =
The errors aren't very helpful but better than nothing if you're debugging JSON sent by a less-than-fully compliant and debugged JSON encoder.
Second, very old web browsers may not have a JSON object with these methods. In that case, you can use the JavaScript function eval
after wrapping the JSON in parenthesis, like this:
>eval('('+json+')') <- Object {result: "ok"}
The eval
function evaluates the string you pass as JavaScript, and the JSON notation is really just a subset of JavaScript. However, you should avoid using eval
whenever you can for a few reasons. First, it's often slower than the methods provided by the JSON
object. Second, it's not safe; your string might contain malicious JavaScript that can crash or otherwise subvert your JavaScript application, which is not a threat you should take lightly. Use the JSON
object whenever it's available. Third, you can use the parse
and stringify
methods to handle simple values, such as Booleans, numbers, and strings; you're not limited to the key-value pairs in the previous example. If all I wanted to do was pass a Boolean (such as "the transaction succeeded!"), I might just write the following:
var jsonSuccess = 'true'; <- "true" > var flag = JSON.parse(jsonSuccess);
Finally, it's worth pointing out that both the parse
and stringify
methods to JSON take an optional replacer function, which is invoked on every key and value in the object being serialized or deserialized. You can use this function to perform on-the-fly data conversions as the JSON is being parsed; for example, you can use it to convert between the string representation of a date and the number of seconds since midnight at the start of the epoch, or to correct the capitalization of strings. I could use a replacer function for either side of the transformation, as shown in the following code, to make the call field lowercase:
> var object = JSON.parse(json, function(k, v) { if ( k == 'call') return v.toLowerCase(); }); <- Object { call:"kf6gpe", type:"l", time:"1399371514", lasttime:"1418597513", lat:37.17667, lng:-122.14650, result: "ok"}
You can also return undefined
to remove an item from the results; to omit the type field from the JSON I generate, I can execute the following:
> var newJson = JSON.stringify(object, function (k, v) { if k == 'type') return undefined; }); <- "{ "call":"KF6GPE","time":"1399371514","lasttime": "1418597513","lat": 37.17667,"lng": -122.14650, "result" : "ok" }"