JavaScript JSON methods, toJSON

The JavaScript Object Notation (JSON) is a notable format for representing objects and values. Initially, this format was created for JavaScript, but several languages also include libraries for handling it. Hence, it is easier to use JSON for data exchange in case the client uses JavaScript, and the server is written on PHP, Ruby, Java, and more.

In general, JavaScript provides two methods of converting: JSON.stringify and JSON.parse. You can use the first one for converting objects into JSON and the second one- for converting JSON back into an object.

JSON.stringify

Let’s consider the following example of the JSON.stringify usage:

let site = {
  name: 'W3Docs',
  hasAdmin: true,
  books: ['html', 'css', 'js', 'git'],
  booksCount: 4,
};
let json = JSON.stringify(site);
console.log(typeof json); // we've got a string!
console.log(json);
/* JSON-encoded object:
{
  "name": "W3Docs",
  "hasAdmin": true,
  "books": ["html", "css", "js", "git"],  
  "booksCount": 4	
}
*/

Please, take into account that a JSON-encoded object differs from the object literal. The main differences are as follows:

  1. Double quotes are used by the string. There shouldn't be any single quotes or backticks in JSON. For example, 'W3Docs' becomes "W3Docs".
  2. Double quotes should be used for object property names, as well. It’s mandatory. For example, booksCount : 4 will become "booksCount": 4.

You can apply the JSON.stringify method to primitives, too. It supports the following data types:

Here is an example:

// a JSON number is an ordinary number
console.log(JSON.stringify(10)) // 10 
// a JSON string is a double-quoted string
console.log(JSON.stringify([1, 2, 3])); // [1,2,3]
console.log(JSON.stringify(false)); // false
console.log(JSON.stringify('W3Docs')) // "W3Docs"

Note that JSON.stringify skips several JavaScript-specific objects, such as function properties (methods), symbolic properties, and properties storing undefined.

Let’s check out the following case:

let site = {
  welcome() { // ignore
    console.log("Welcome");
  },
  [Symbol("id")]: 10, // ignore
  someProperty: undefined // ignore
};
console.log(JSON.stringify(site)); // {} - empty object

The best thing about it is that the nested objects are automatically supported and converted.

For example:

let site = {
  name: "W3Docs",
  books: {
    booksCount: 4,
    booksTitle: ["html", "css", "js", "git"]
  }
}; 
console.log(JSON.stringify(site));
/* The whole structure is stringified:
{
  "name":"W3Docs",
  "book":{"booksCount":4,"booksTitle":["html","css", "js", "git"]},
}
*/

But, there is an essential limitation as well: you must not use circular references.

For example:

let books = {
  booksCount: 4
};
let site = {
  name: "W3Docs",
  booksTitle: ["html", "css", "js", "git"]
};
site.tutorial = books; // site references books
books.canUse = site; // books references site
console.log(JSON.stringify(site)); // Error: Converting circular structure to JSON

Excluding and Transforming: replacer

For JSON.stringify the following full syntax is used:

let json = JSON.stringify(value[, replacer, space])

It has three arguments:

  • the value: a value for encoding;
  • the replacer: the array of properties for encoding or a mapping function function(key, value);;
  • the space:amount of space that is used for formatting.

JSON.stringify uses the first argument most of the time. But if you wish to improve your replacement process, you can also use the second argument. If an array of properties is passed to it, only these properties are encoded.

Let’s have a look at the example:

let books = {
  booksCount: 4
};
let site = {
  name: "W3Docs",
  booksTitle: [{
    title: "html"
  }, {
    title: "css"
  }, {
    title: "js"
  }, {
    title: "git"
  }],
  tutorial: books // tutorial references books
};
books.canUse = site; // books references site
console.log(JSON.stringify(site, ['name', 'booksTitle']));
// {"name":"W3Docs","booksTitle":[{},{},{},{}]}
let books = {
  booksCount: 4
};
let site = {
  name: "W3Docs",
booksTitle: [{
    title: "html"
  }, {
    title: "css"
  }, {
    title: "js"
  }, {
    title: "git"
  }], 
  tutorial: books // site references books
};
books.canUse = site; //books references site 
console.log(JSON.stringify(site, ['name', 'booksTitle', 'tutorial', 'title', 'booksCount']));
/*
{
  "name":"W3Docs",
  "booksTitle":[{"title":"html"},{"title":"css"}, {"title":"js"}, {"title":"git"}],
  "tutorial":{"booksCount":4}
}
*/

Now, let’s try to add in the list all the properties, excluding the books.free:

As you can see, everything is serialized, except canUse. You can also notice that the given list looks rather long. Luckily, the replacer function can be called. You can call it for every key, value pair, and the “replaced” value may be returned. You can use it instead of the original value. For ignoring the canUse the undefined is returned in the example below:

let books = {
  booksCount: 4
};
let site = {
  name: "W3Docs",
  booksTitle: [{
    title: "html"
  }, {
    title: "css"
  }, {
    title: "js"
  }, {
    title: "git"
  }],
  tutorial: books // site references books
};
books.canUse = site; // books references site
console.log(JSON.stringify(site, function replacer(key, value) {
  console.log(`${key}: ${value}`);
  return (key == 'canUse') ? undefined : value;
}));
/* key:value pairs that come to replacer:
:             [object Object]
name:        W3Docs
booksTitle: [object Object],[object Object],[object Object],[object Object]
0:            [object Object]
title:         html
1:            [object Object]
title:         css
2:            [object Object]
title:         js
3:            [object Object]
title:         git
tutorial:        [object Object]
booksCount:       4
*/

Take into account that the replacer function gets any key/value pair along with array items and nested objects.

Formatting:space

As it was already mentioned, JSON.stringify has three arguments. The third one is the number of spaces used for formatting. Commonly, developers use the space argument to reach an excellent output.

The space = 2 orders JavaScript to display the nested objects on various lines with indentation of two spaces inside an object.

For instance:

let user = {
  name: "Maria",
  age: 23,
  roles: {
    isAdmin: true,
    isContentWriter: false
  }
};
console.log(JSON.stringify(user, null, 2));
/* two-space indents:
{
  "name": "Maria",
  "age": 23,
  "roles": {
    "isAdmin": true,
    "isContentWriter": false
  }
}
*/
/* for JSON.stringify(user, null, 2) the result would be more indented:
{
  name: "Maria",
  age: 23,
  roles: {
    isAdmin: true,
    isContentWriter: false
  }
};
*/

Custom “toJSON”

As a rule, an object can provide the method toJSON for implementing the to-JSON conversion. If it’s available, the JSON.stringify automatically calls it.

Here is an example:

let books = {
  booksCount: 4
};  
let site = {
  name: "W3Docs",
  update: new Date(Date.UTC(2020, 1, 2)),
  books
}; 
console.log(JSON.stringify(site));
/*
  {
    "name":"W3Docs",
    "update":"2020-02-02T00:00:00.000Z",  // (1)
    "books": {"booksCount":4 }              // (2)
  }
*/

In the case above, the update (1) is transformed into a string. The reason is that all the dates have a built-in toJSON method.

If you add a custom toJSON for the books (2) object, it will look as follows:

let books = {
  booksCount: 4,
  toJSON() {
    return this.booksCount;
  }
}; 
let site = {
  name: "W3Docs",
  books
}; 
console.log(JSON.stringify(books)); // 4 
console.log(JSON.stringify(site));
/*
  {
    "name":"W3Docs",
    "books": 4
  }
*/

JSON.parse

For decoding a JSON-string another method is used, called JSON.parse with the following syntax:

let value = JSON.parse(str, [reviver]);

JSON is somewhat complicated: objects and arrays may include other objects and arrays. But it’s compulsory to obey the format of JSON.

Below, you can find the typical mistakes in hand-written JSON:

let json = `{
  welcome: "Welcome",                     // mistake: property name without quotes
  "site": 'W3Docs',               // mistake: single quotes in value (must be double)
  'hasAdmin': true                  // mistake: single quotes in key (must be double)
  "update": new Date(2000, 2, 3), // mistake: no "new" is allowed, only bare values
  "books": [1, 2, 3, 4]              // here all fine
}`;

Also, note that JSON doesn’t allow commenting. In case you add a comment to it, you will make it invalid. There is a unique format JSON, which supports unquoted keys, comments, and more.

Summary

JSON represents a data format with independent standard and libraries for the majority of programming languages. It supports arrays, strings, objects, booleans, numbers, and null.

JavaScript has the methods JSON.stringify for serializing into JSON and JSON.parse for reading from JSON. In case an object has toJSON, you need to call it by JSON.stringify..




Do you find this helpful?

Related articles