JSON - Dynamic HTML5 Web Applications with JavaScript and jQuery - HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

Part II Dynamic HTML5 Web Applications with JavaScript and jQuery

Lesson 15 JSON

JSON (commonly pronounced Jason) stands for JavaScript Object Notation. It is a data format for representing the properties of a JavaScript object as a string.

In computing, there are often instances where you need to convert data from one format to another. For instance, if you consider a JavaScript object, you may want to convert it into a String so that:

· You can send it across a network to another computer.

· You can store it in a file.

· You can use it with other JavaScript APIs that only support strings.

Conversely, you may eventually want to convert this string back into an object so that you can use it in your JavaScript application.

The process of converting an object into a string is referred to as serialization, while the process of converting it back is referred to as de-serialization.

In order to convert an object into a string, you need a data-format that specifies how the object should be mapped to a character string—for instance, how do you denote the properties and values of an object, and how do you encode the various data types such as numbers and arrays?

Historically most data formats have been binary: This meant that it was not possible for a human to read the formatted data and gain an understanding of its underlying structure or meaning. Typically, data was converted to and from the binary format using a proprietary algorithm.

In recent years, there has been a move toward plain-text data formats. The most notable example is XML, which uses a similar structure and syntax to HTML in order to differentiate properties from their values.

There is nothing inherently wrong with using XML to serialize JavaScript objects, and many web applications do use XML. For instance, this is a possible representation of a contact in XML:

<?xml version="1.0" encoding="UTF-8"?>

<contact>

<contactName>William Jones</contactName>

<phoneNumber>555-2941</phoneNumber>

<emailAddress>william@testing.com</emailAddress>

<company>

<code>123</code>

<name>ABC Incorporated</name>

</company>

<notes></notes>

<lastContacted>2014-09-25</lastContacted>

</contact>

There are three main drawbacks with XML:

· The ratio of tags to content in XML is reasonably high: In the previous example, far more than half the message consists of tags.

· A JavaScript library is required to convert between the JavaScript object and XML because JavaScript does not natively support XML.

· Although XML is simple in principle, numerous technologies have grown up around it, such as namespaces and schemas, and they can complicate XML considerably.

JSON alleviates all of these issues. The main beauty of JSON is that it maps directly to JavaScript. If you were to write out the structure of a JavaScript object on paper using the same syntax JavaScript uses for declaring objects, it would probably look identical to JSON.

JSON is also natively supported in the latest versions of JavaScript; therefore you do not need any libraries to work with JSON.

Finally, JSON is incredibly simple. It is described in a few hundred words on the following website: http://http://www.json.org.

The JSON representation of a contact may look like this:

{

"contactName":"William Jones",

"phoneNumber":"555-2941",

"emailAddress":"william@testing.com",

"company":{

"code":123,

"name":"ABC Incorporated"

},

"notes":null,

"lastContacted":"2014-06-30T05:50:46.659Z"

}

Notice how similar this looks to the literal notation for declaring a JavaScript object?

It is possible to convert a JavaScript object into a string using the utility function JSON.stringify. In order to demonstrate this, start by creating a contact object using the object literal notation:

> c1 = {

contactName: "William Jones",

phoneNumber:"555-2941",

emailAddress:"william@testing.com",

company:{

code:123,

name:"ABC Incorporated"

},

notes:null

lastContacted: new Date()

}

Next, execute the following to store this as a string in the variable contactString:

> contactString = JSON.stringify(c1)

"{"contactName":"William Jones","phoneNumber":"555-2941","emailAddress":"william@testing.com","company":{"code":123,"name":"ABC Incorporated"},"notes":null,"lastContacted":"2014-06-30T06:06:56.306Z"}"

Notice that the properties and values are all retained, but property names are all automatically embedded in double quotes.

JSON allows all the JavaScript data types to be represented in the serialized version. This ensures that when the string is eventually converted back into an object, the various properties retain their original data types.

· Strings always appear inside double quotes. Multiple examples can be seen in this example—for instance “William Jones”.

· Numbers appear literally, and do not need to be quoted; for instance, the code property has a value of 123.

· Although not shown in this example, Boolean values are represented with the unquoted keywords true and false.

· The unquoted keyword null is used to represent a null value, as you can see with the notes property.

· Objects can encapsulate child objects, as the company property demonstrates. This nesting can go to as many levels as you require.

· Arrays can be used as the value for any property. These use the familiar square brackets to indicate the start and end of the array, while elements are separated with commas.

You can convert the string back into an object using the JSON.parse function. The example in Figure 15.1 shows this and demonstrates that you can access the properties of the de-serialized object:

image

Figure 15.1

Although the JSON format is great for serializing properties, it cannot be used for serializing methods: Any methods present on the object are simply ignored when JSON.stringify is invoked.

Replacing and Reviving

Although JavaScript is great for working with most JavaScript data types, it does come with certain limitations. One of the most difficult data types to handle is the Date object.

There are many different ways to serialize dates. For instance, you could use their time in milliseconds:

new Date().getTime()

1404088573560

The time in milliseconds is a number that represents the number of milliseconds that have passed since midnight on January 1, 1970. This is not an ideal way to represent a date; among other reasons, it does not contain time-zone information.

You could also use the toString method on the Date object:

new Date().toString()

"Mon Jun 30 2014 12:36:01 GMT+1200 (New Zealand Standard Time)"

This is better because it does contain time-zone information. However, it also contains unnecessary information: The day of the week is implied by the date.

Ultimately, it does not really matter what format you choose, as long as it stores all the information you require. The most important thing is that everyone agrees on the same format, thereby allowing any serialized objects to be de-serialized by your web application.

For this reason, the JavaScript Date object now supports a method called toJSON, as you can see in the following example:

new Date().toJSON();

"2014-06-30T00:37:09.348Z"

This produces a date in the UTC time zone (essentially the same as Greenwich Mean Time), regardless of the time zone of the computer itself. The timezone is denoted by the trailing Z on the date format. The entire date/time string is formatted according to an ISO standard, which is widely used in computing.

If you look at the JSON example earlier in this lesson, you will see that the date was converted into a string conforming to this standard.

You may have noticed a problem in our example, however. When JSON.parse was used to transform the string back into an object, the lastContacted property was left as a string, rather than converted back into a Date object.

This is not the desired 'margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;vertical-align:baseline'>The JSON.parse function supports an optional second parameter referred to as a “reviver.” This can be used to convert values as they are transformed back onto the object. This parameter expects to be passed a function, which in turn will be passed every property as it is parsed. Where appropriate, the reviver can decide to modify the value of the property before it is set on the object.

In order to parse dates with a reviver function, you need to perform two tasks:

· Identify that a value is a date. The most common way to do this is with regular expressions.

· Convert it from a string to a Date object. The Date object has a constructor that supports the ISO format; therefore, this is a simple process.

You saw regular expressions earlier in the book when you validated form fields. JavaScript supports a literal notation for defining regular expressions: Any unquoted character string that starts with a forward slash is assumed to be a regular expression.

The regular expression that follows is reasonably complex, so it is not important that you understand it, but you should understand the approach:

dateReviver = function(name, value) {

var regExp = /ˆ(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/

if (value && typeof value === 'string' && value.match(regExp)) {

return new Date(value);

} else {

return value;

}

}

This code starts by defining a regular expression that describes the pattern of characters you expect to find in a date field.

Next, the if statement checks that you have been passed a value and that the value has a data type of string. Finally, the if statement checks whether the value matches the regular expression: If it does, then the match method will return a non-null value.

If the value is determined to be a serialized version of a date, it is simply passed to the constructor of Date, and the resulting object is returned. If it is not a date, you simply return the value untouched.

You can now use this function to de-serialize the contact into a new variable:

contact2 = JSON.parse(contactString, dateReviver);

If you now examine the lastContacted property, you can confirm it is a Date:

> typeof contact2.lastContacted

"object"

> contact2.lastContacted.toString()

"Mon Jun 30 2014 18:06:56 GMT+1200 (NZST)"

Notice that even though the serialized version used the UTC time zone, the de-serialized version has been converted back into my local time zone.

Just as the JSON.parse function supports a reviver, the JSON.stringify function supports an optional replacer function. This is identical to the reviver, except it allows you to convert values as they are serialized.

Try It

In this Try It, we will experiment with the JSON data format. As you have already seen, JSON is an extremely simple data format so you will use it for a slightly different purpose: cloning objects. To clone an object is to make a copy of it: We will look at how this can be achieved with JSON.

Lesson Requirements

In order to complete this lesson, you will need the Chrome web browser. You may, however, want to complete these exercises in a text editor and copy the results to the console.

Step-by-Step

1. Start by creating a sample object that you can clone. Make sure that this contains child objects and arrays. My object looked like this:

2. o = {

3. studentName: 'William Jones',

4. school: 'Middletown High School',

5. grades: [

6. {subject: 'English',

7. grade: 'A'},

8. {subject: 'Algebra',

9. grade: 'B+'},

10. {subject: 'Geometry',

11. grade: 'C'},

12. ]

}

2. Create a clone function; this should declare a single parameter, which is the object to clone.

3. Within the function, call JSON.stringify on the object passed in, and store the result in a new variable.

4. Parse the string stored in Step 3 using JSON.parse, and store the result in a new variable.

5. Return the newly created object from the function.

6. Confirm that you can change the value of properties in the newly created object and that these are not reflected in the original object.

Reference

Please go to the book's website at www.wrox.com/go/html5jsjquery24hr to view the video for Lesson 15, as well as download the code and resources for this lesson.