A brief overview of JSON

JavaScript Object Notation (JSON) is an open, text-based data exchange format based on JavaScript's object literal notation. Here we learn how to safely convert a JSON string (message) into a JavaScript object and vice versa, then review a customizable webpage example.

Using JSON

The JSON format is often used for serializing and transmitting structured data over a network connection, such as between a server and web application. Be aware, however, that JSON can be used in virtually any scenario where software components need to exchange or store structured information as text.

Consider the following JavaScript JSON formatted string:

'{"firstName":"John","lastName":"Doe","phone":"958-555-0100","age":25}'

This string provides structured, text-based information about a person (John Doe, in this case) and can be safely converted into a JavaScript object by using the JSON object's parse method:

var person = JSON.parse('{"firstName":"John","lastName":"Doe","phone":"958-555-0100","age":25}');

Important  The eval method can be used perform the same JSON.parse operation. Whenever possible, use JSON.parse to de-serialize JSON text. The JSON.parse function is more secure and executes faster than the eval function.

After the JSON string has been converted into a JavaScript object, the age of person simply becomes person.age:

alert("The value of the 'age' property for the 'person' object is: " + person.age);

Using JSON.stringify, the inverse is just as simple:

var JavaScriptObjectLiteral = {
  firstName: "John",
  lastName: "Doe",
  age: 25
}
alert( JSON.stringify(JavaScriptObjectLiteral) );

In other words, given a JavaScript object, JSON.stringify returns the equivalent JSON formatted string. This can be quite handy, as shown in the following example.

A customizable webpage

Consider a website where a user has the option of locally "logging" into the site. This local login information (or "credentials") could be used for a myriad of purposes including allowing the user to customize the site to their liking. For example, the user could supply a name and an optional password for a particular client-side customization. For pedagogical reasons, the only allowed customization is a change of background color. This core idea, however, can be extended to much more complex customization scenarios.

Before examining the following example, be aware that the window.localStorage object is generally only available when the page is served from a webserver. Thus, locally saving and viewing (running) the following example might not work as expected. Instead, view the example from a live webserver: JSON - A Breif Overview. A screen shot of JSON - A Breif Overview follows.

First screen shot

Note  Before proceeding, review the code shown in the previous image. To do so, navigate to JSON - A Breif Overview, right-click the page and choose View source.

The markup section of the code is essentially composed of two forms (<form>), one visible and the other initially hidden. The visible credentialsForm form collects the user's credentials and calls getCredentials(this.form) when the Submit button is clicked. Be aware that this.form passes a form reference to the getCredentials function:

function getCredentials(credentialsFormObject) {
  userToken.user = sanitizeHTML(credentialsFormObject.user.value);
  userToken.password = sanitizeHTML(credentialsFormObject.pwd.value);
  
  if ( newUser() ) {
    document.getElementById('backgroundColorForm').style.display = "block";      
  }
  else {
    setCustomizations();
  }
}

The algorithm for getCredentials is straightforward:

  • Place the sanitized user credentials into the global variable userToken (so that this information can be accessed easily by other functions).
  • Call newUser to determine if the user's credentials indicates that this is a new user. If so, display the backgroundColorForm form. Otherwise, set the background color to the user's previously saved color preference by calling setCustomizations.

The code for newUser is as follows:

function newUser() {
  var JSON_userTokens = window.localStorage.userTokens;
  
  if (!JSON_userTokens) { 
    return true;
  }
  
  var userTokens = JSON.parse(JSON_userTokens);
  
  for (var i = 0; i < userTokens.length; i++) {
    if (userTokens[i].user == userToken.user && userTokens[i].password == userToken.password) {
      userToken.backgroundColor = userTokens[i].backgroundColor;
      return false; // This user already exists.
    }
  }
  
  return true;
}

The window.localStorage.userTokens property returns a (possibly empty) JSON formatted "string array" of user tokens associated with this user's domain and places it in JSON_userTokens. The "string array" is turned into a true JavaScript array via JSON.parse(JSON_userTokens). We then iterate through the elements of the array to determine if userToken is a known user and if so:

  • Save the user's previously saved background color preference to the global userToken (for later use by setCustomizations).
  • Return false indicating that this is not a new user (but a known user).

If newUser returns false, the function setCustomizations is called (see the if-then statement of getCredentials earlier). setCustomizations assumes that the user indicated via userToken is known and therefor directly sets the background color of the page to the user's previously saved preference:

function setCustomizations() {
  document.getElementsByTagName('body')[0].style.backgroundColor = userToken.backgroundColor;  
}

If, on the other hand, newUser returns true, only the backgroundColorForm form is displayed (as shown in this fragment from getCredentials):

if ( newUser() ) {
  document.getElementById('backgroundColorForm').style.display = "block";      
}

This results in output similar to the following:

Screen shot

When the new user enters a CSS color string, such as "#543" or "cyan" and the Submit button is clicked, getBackgroundColor(this.form) is invoked:

function getBackgroundColor(backgroundFormObject) {
  userToken.backgroundColor = sanitizeHTML(backgroundFormObject.cssColor.value);
  addUser();
  setCustomizations(); 
  document.getElementById('backgroundColorForm').style.display = "none";                      
}

The entered color string is retrieved from the form's input element (named cssColor) and stored in the global userToken. Next, the addUser function is called:

function addUser() {
  var userTokens = [];
  var JSON_userTokens = window.localStorage.userTokens;
  
  if (JSON_userTokens) { 
    userTokens = JSON.parse(JSON_userTokens);
  }
  
  userTokens.push(userToken);
  window.localStorage.userTokens = JSON.stringify(userTokens);
}

This adds the new user's information (userToken) to persistent local storage. The JSON.stringify and JSON.parse conversions are necessary in that Web Storage can only store string key/value pairs.

Finally, setCustomizations is called to set the background color to the just obtained user's preference, and the backgroundColorForm form is re-hidden.

Flexibility of web storage and JSON

Because Web Storage only allows strings (in the form of key/value pairs), JSON can be used to convert complex JavaScript objects into easily storable JSON strings and vice versa. Since allowed Web Storage allocations are much larger (megabytes) than typical cookie storage allocations (kilobytes), Web Storage in conjunction with JSON can provide a number of interesting scenarios including local user website customization, as outlined in the preceding example.

How to save files locally using Web Storage

Web Storage