JSON (“JavaScript Object Notation”) is a storage format that uses text to encode data. Its syntax is a subset of JavaScript expressions. As an example, consider the following data, stored as text in a file :

    JavaScript has the global namespace object JSON provides methods for creating and parsing JSON.

    A specification for JSON was published by Douglas Crockford in 2001, at . He explains:

    Later, JSON was standardized as ECMA-404:

    • 1st edition: October 2013
    • 2nd edition: December 2017

    41.1.1. JSON’s grammar is frozen

    Quoting the ECMA-404 standard:

    Therefore, JSON will never get improvements such as optional trailing commas, comments or unquoted keys – independently of whether or not they are considered desirable. However, that still leaves room for creating supersets of JSON that compile to plain JSON.

    41.2. JSON syntax

    JSON consists of the following parts of JavaScript:

    • Compound:
      • Object literals:
        • Keys are double-quoted strings.
        • Values are JSON values.
        • No trailing commas are allowed.
      • Array literals:
        • Elements are JSON values.
        • No holes or trailing commas are allowed.
    • Atomic:
      • null (but not undefined)
      • Booleans
      • Numbers (excluding NaN, +Infinity, -Infinity)
      • Strings (must be double-quoted)
        As a consequence, you can’t (directly) represent cyclic structures in JSON.

    The global namespace object JSON contains methods for working with JSON data.

    41.3.1. JSON.stringify(value, replacer?, space?)

    .stringify() converts a JavaScript value to a JSON string.

    41.3.1.1. Result: a single line of text

    If you only provide the first argument, .stringify() returns a single line of text:

    1. JSON.stringify({foo: ['a', 'b']}),
    41.3.1.2. Result: a tree of indented lines

    If you provide a non-negative integer for space (we are ignoring replacer here, which is explained ), then .stringify() returns one or more lines and indents by space spaces per level of nesting:

    1. assert.equal(
    2. `{
    3. "a",
    4. ]
    41.3.1.3. Details on how JavaScript values are stringified

    Supported primitive values are stringified as expected:

    1. '"abc"'
    2. '123'
    3. 'null'
    1. 'null'
    2. 'null'

    Unsupported primitive values are stringified as undefined:

    1. undefined
    2. undefined

    Functions are stringified as undefined:

    1. undefined

    In an Array, elements that would be stringified as undefined, are stringified as 'null':

    1. '[null,123,null]'

    In an object (that is neither an Array nor a function), properties, whose values would be stringified as undefined, are skipped:

    If an object (which may be an Array or a function) has a method .toJSON(), then the result of that method is stringified, instead of the object. For example, Dates have a method .toJSON() that returns strings.

    1. > JSON.stringify(new Date(2999, 11, 31))

    For more details on stringification, consult the ECMAScript specification.

    41.3.2. JSON.parse(text, reviver?)

    .parse() converts a JSON text to a JavaScript value:

    1. > JSON.parse('{"foo":["a","b"]}')

    The parameter reviver is explained later.

    41.3.3. Example: converting to and from JSON

    The following class demonstrates one technique for implementing the conversion from and to JSON:

    1. class Point {
    2. return new Point(jsonObj.x, jsonObj.y);
    3. this.coord = [x, y];
    4. toJSON() {
    5. return {x, y};
    6. }
    7. JSON.stringify(new Point(3, 5)),
    8. assert.deepEqual(
    9. new Point(3, 5));

    The method .toJSON() is used when stringifying instances of Point.

    41.4. Configuring what is stringified or parsed (advanced)

    What is stringified or parsed, can be configured as follows:

    • .stringify() has the optional parameter replacer that contains either:
      • An Array with names of properties. When stringifying an object (that may be nested) only those properties will be considered, all others will be ignored.
      • A value visitor – a function that can transform JavaScript values before they are stringified.
    • .parse() has the optional parameter reviver – a value visitor that can transform the parsed JSON data before it is returned.

    41.4.1. .stringfy(): specifying the only properties that objects should have

    If the second parameter of .stringify() is an Array, then only object properties, whose names are mentioned in the Array, are included in the result:

    1. const obj = {
    2. b: {
    3. d: 3,
    4. };
    5. JSON.stringify(obj, ['b', 'c']),

    41.4.2. .stringify() and .parse(): value visitors

    What I call a value visitor is a function that transforms JavaScript values (compound or atomic):

    • JSON.stringify() calls the value visitor in its parameter replacer before it stringfies the JavaScript value it received.
    • JSON.parse() calls the value visitor in its parameter reviver after it parsed the JSON data.
      A JavaScript value is transformed as follows: The value is either atomic or compound and contains more values (nested in Arrays and objects). The atomic value or the nested values are fed to the value vistor, one at a time. Depending on what the visitor returns, the current value is removed, changed or preserved.

    The parameters are:

    • value: The current value.
    • this: Parent of current value. The parent of the root value r is {'': r}.
    • key: Key or index of the current value inside its parent. The empty string is used for the root value.
      The value visitor can return:

    • value: means there won’t be any change.

    • A different value x: leads to value being replaced with x.
    • undefined: leads to value being removed.

    41.4.3. Example: visiting values

    The following code demonstrates in which order a value visitor sees values.

    1. function valueVisitor(key, value) {
    2. return value; // no change
    3. a: 1,
    4. c: 2,
    5. }
    6. JSON.stringify(root, valueVisitor);
    7. { key: '', value: root, this: { '': root } },
    8. { key: 'b', value: root.b, this: root },
    9. ]);

    As you can see, .stringify() visits values top-down (root first, leaves last). In contrast, .parse() visits values bottom-up (leaves first, root last).

    41.4.4. Example: stringifying unsupported values

    .stringify() has no special support for regular expression objects – it stringifies them as if they were plain objects:

    1. const obj = {
    2. };
    3. JSON.stringify(obj),

    We can fix that via a replacer:

    41.4.5. Example: parsing unsupported values

    To .parse() the result from the previous section, we need a reviver:

    1. // Very simple check
    2. return new RegExp(value.source, value.flags);
    3. return value;
    4. }
    5. "name": "abc",
    6. "__type__": "RegExp",
    7. "flags": "iu"
    8. }`;
    9. JSON.parse(str, reviver),
    10. name: 'abc',
    11. });

    41.5.1. Why doesn’t JSON support comments?

    Douglas Crockford explains why in a Google+ post from 1 May 2012:

    41.6. Quick reference: JSON

    Signature of value visitors:

    1. type ValueVisitor = (this: object, key: string, value: any) => any;

    JSON:

    • .stringify(value: any, replacer?: ValueVisitor, space?: string | number): string [ES5]

    Convert value to a JSON string. The parameter replacer is explained . The parameter space works as follows:

    • If space is omitted, .stringify() returns a single line of text.
    1. assert.equal(
    2. '{"foo":1,"bar":[2,3]}');
    • If space is a number, .stringify() returns one or more lines and indents them by space spaces per level of nesting.
    1. JSON.stringify({foo: 1, bar: [2, 3]}, null, 2),
    2. "foo": 1,
    3. 2,
    4. ]
    • If space is a string, it is used to indent.
    1. assert.equal(
    2. `{
    3. >>"bar": [
    4. >>>>3
    5. }`);
    • .stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string [ES5]

    If replacer is an Array, then the result only includes object properties whose names are mentioned in the Array.

    1. '{"foo":1}'
    • .parse(text: string, reviver?: ValueVisitor): any [ES5]
    1. JSON.parse('{"a":true,"b":[1,2]}'),

    41.6.1. Sources