JSON

JSON format

The JSON format (abbreviation of JavaScript Object Notation) is a text format for data exchange. It was proposed by Douglas Crockford in 2001 to replace the cumbersome and cumbersome XML format.

Compared with the XML format, the JSON format has two significant advantages: simple to write and clear at a glance; it conforms to the native JavaScript syntax and can be directly processed by the interpretation engine without adding additional parsing code. Therefore, JSON has been quickly accepted and has become a standard format for data exchange among major websites and has been written into the standard.

Each JSON object is a value, which may be an array or object, or it may be a value of a primitive type. In short, it can only be one value, not two or more values.

JSON has strict regulations on the type and format of values.

  1. The value of a composite type can only be an array or an object, not a function, regular expression object, or date object.

  2. There are only four primitive types of values: string, numeric value (must be expressed in decimal), boolean and null (NaN, Infinity, -Infinity and undefined cannot be used).

  3. The string must be expressed in double quotation marks, not single quotation marks.

  4. The key name of the object must be enclosed in double quotes.

  5. No comma can be added after the last member of an array or object.

The following are all valid JSON.

["one", "two", "three"]

{"one": 1, "two": 2, "three": 3}

{"names": ["Zhang San", "李四"]}

[{"name": "张三"}, {"name": "李四"}]

The following are all illegal JSON.

{name: "Zhang San",'age': 32} // The attribute name must use double quotes

[32, 64, 128, 0xFFF] // Hexadecimal values ​​cannot be used

{"name": "Zhang San", "age": undefined} // Undefined cannot be used

{"name": "Zhang San",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName": function () {
      return this.name;
  }
} // Function and date objects cannot be used for attribute values

Note that null, empty arrays and empty objects are all legal JSON values.

JSON Object

The JSON object is a native JavaScript object, used to process data in JSON format. It has two static methods: JSON.stringify() and JSON.parse().

JSON.stringify()

Basic usage

The JSON.stringify() method is used to convert a value into a JSON string. The string conforms to the JSON format and can be restored by the JSON.parse() method.

JSON.stringify("abc"); // ""abc""
JSON.stringify(1); // "1"
JSON.stringify(false); // "false"
JSON.stringify([]); // "[]"
JSON.stringify({}); // "{}"

JSON.stringify([1, "false", false]);
//'[1,"false",false]'

JSON.stringify({ name: "张三" });
//'{"name":"Zhang San"}'

The above code converts various types of values ​​into JSON strings.

Note that for strings of primitive types, the conversion result will be enclosed in double quotes.

JSON.stringify("foo") === "foo"; // false
JSON.stringify("foo") === '"foo"'; // true

In the above code, the string foo is converted to "\"foo\"". This is because when restoring in the future, the inner double quotes can let the JavaScript engine know that this is a string and not other types of values.

JSON.stringify(false); // "false"
JSON.stringify("false"); // "\"false\""

In the above code, if it is not the inner double quotation mark, the engine will not know whether the original value is a Boolean value or a string when it is restored in the future.

If the property of the object is undefined, function or XML object, the property will be filtered by JSON.stringify().

var obj = {
  a: undefined,
  b: function () {},
};

JSON.stringify(obj); // "{}"

In the above code, the a property of the object obj is undefined, and the b property is a function, and the result is filtered by JSON.stringify.

If the members of the array are undefined, functions, or XML objects, these values ​​are converted to null.

var arr = [undefined, function () {}];
JSON.stringify(arr); // "[null,null]"

In the above code, the members of the array arr are undefined and functions, and they are all converted to null.

Regular objects will be converted into empty objects.

JSON.stringify(/foo/); // "{}"

The JSON.stringify() method ignores the non-traversable properties of the object.

var obj = {};
Object.defineProperties(obj, {
  foo: {
    value: 1,
    enumerable: true,
  },
  bar: {
    value: 2,
    enumerable: false,
  },
});

JSON.stringify(obj); // "{"foo":1}"

In the above code, bar is a non-traversable property of the obj object, and the JSON.stringify method will ignore this property.

The second parameter

The JSON.stringify() method can also accept an array as the second parameter to specify which properties of the parameter object need to be converted into strings.

var obj = {
  prop1: "value1",
  prop2: "value2",
  prop3: "value3",
};

var selectedProperties = ["prop1", "prop2"];

JSON.stringify(obj, selectedProperties);
// "{"prop1":"value1","prop2":"value2"}"

In the above code, the second parameter of the JSON.stringify() method is specified, and only the two properties of prop1 and prop2 are transferred.

This whitelist-like array is only valid for the properties of the object, not for the array.

JSON.stringify(["a", "b"], ["0"]);
// "["a","b"]"

JSON.stringify({ 0: "a", 1: "b" }, ["0"]);
// "{"0":"a"}"

In the above code, the second parameter specifies that the JSON format only transfers the 0 attribute, which is actually invalid for arrays, only valid for objects.

The second parameter can also be a function to change the return value of JSON.stringify().

function f(key, value) {
  if (typeof value === "number") {
    value = 2 * value;
  }
  return value;
}

JSON.stringify({ a: 1, b: 2 }, f);
//'{"a": 2,"b": 4}'

The f function in the above code accepts two parameters, which are the key name and key value of the converted object. If the key value is a numeric value, it is multiplied by 2, otherwise it is returned as is.

Note that this processing function processes all keys recursively.

var obj = { a: { b: 1 } };

function f(key, value) {
  console.log("[" + key + "]:" + value);
  return value;
}

JSON.stringify(obj, f);
// []:[object Object]
// [a]:[object Object]
// [b]:1
//'{"a":{"b":1}}'

In the above code, the object obj will be processed three times by the f function, and the last line of output is the default output of JSON.stringify(). The first time the key name is empty, the key value is the entire object obj; the second time the key name is a, the key value is {b: 1}; the third time the key name is b, the key value Is 1.

In recursive processing, each processed object is the value returned in the previous time.

var obj = { a: 1 };

function f(key, value) {
  if (typeof value === "object") {
    return { b: 2 };
  }
  return value * 2;
}

JSON.stringify(obj, f);
// "{"b": 4}"

In the above code, the f function modifies the object obj, and then the JSON.stringify() method recursively processes the modified object obj.

If the processing function returns undefined or has no return value, the property will be ignored.

function f(key, value) {
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

JSON.stringify({ a: "abc", b: 123 }, f);
//'{"b": 123}'

In the above code, after the a property is processed, it returns undefined, so the property is ignored.

The third parameter

JSON.stringify() can also accept a third parameter to increase the readability of the returned JSON string.

By default, a single-line string is returned. For large JSON objects, the readability is very poor. The third parameter makes each attribute occupies a separate line, and add the specified prefix (no more than 10 characters) in front of each attribute.

// Default output
JSON.stringify({ p1: 1, p2: 2 });
// JSON.stringify({ p1: 1, p2: 2 })

// Branch output
JSON.stringify({ p1: 1, p2: 2 }, null, "\t");
// {
// "p1": 1,
// "p2": 2
//}

In the above example, the third attribute \t adds a tab character in front of each attribute, and then displays it in separate lines.

If the third attribute is a number, it means the space added in front of each attribute (maximum 10).

JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/*
"{
  "p1": 1,
  "p2": 2
}"
*/

The toJSON() method of the parameter object

If the parameter object has a custom toJSON() method, then JSON.stringify() will use the return value of this method as a parameter, ignoring other properties of the original object.

Below is an ordinary object.

var user = {
  firstName: "Three",
  lastName: "Zhang",

  get fullName() {
    return this.lastName + this.firstName;
  },
};

JSON.stringify(user);
// "{"firstName":"三","lastName":"张","fullName":"张三"}"

Now, add the toJSON() method to this object.

var user = {
  firstName: "Three",
  lastName: "Zhang",

  get fullName() {
    return this.lastName + this.firstName;
  },

  toJSON: function () {
    return {
      name: this.lastName + this.firstName,
    };
  },
};

JSON.stringify(user);
// "{"name":"Zhang San"}"

In the above code, JSON.stringify() finds that the parameter object has a toJSON() method, and directly uses the return value of this method as a parameter, and ignores other parameters of the original object.

The Date object has its own toJSON() method.

var date = new Date("2015-01-01");
date.toJSON(); // "2015-01-01T00:00:00.000Z"
JSON.stringify(date); // ""2015-01-01T00:00:00.000Z""

In the above code, JSON.stringify() finds that it is dealing with a Date object instance, and it will call the toJSON() method of this instance object with the return value of the method as a parameter.

One application of the toJSON() method is to automatically convert regular objects into strings. Because JSON.stringify() cannot convert regular objects by default, but after setting the toJSON() method, you can convert regular objects.

var obj = {
  reg: /foo/,
};

// When the toJSON method is not set
JSON.stringify(obj); // "{"reg":{}}"

// When setting the toJSON method
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/); // ""/foo/""

The above code deploys the toJSON() method on the prototype of the regular object and points it to the toString() method. Therefore, when converting to JSON format, the regular object first calls the toJSON() method to convert it to a string. Then it is processed by the JSON.stringify() method.

JSON.parse()

The JSON.parse() method is used to convert JSON strings into corresponding values.

JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse("null"); // null

var o = JSON.parse('{"name": "张三"}');
o.name; // Zhang San

If the input string is not in a valid JSON format, the JSON.parse() method will report an error.

JSON.parse("'String'"); // illegal single quotes
// SyntaxError: Unexpected token ILLEGAL

In the above code, the double-quoted string is a single-quoted string. Because the single-quoted string does not conform to the JSON format, an error is reported.

In order to handle parsing errors, you can put the JSON.parse() method in the try...catch code block.

try {
  JSON.parse("'String'");
} catch (e) {
  console.log("parsing error");
}

The JSON.parse() method can accept a processing function as the second parameter, and the usage is similar to the JSON.stringify() method.

function f(key, value) {
  if (key === "a") {
    return value + 10;
  }
  return value;
}

JSON.parse('{"a": 1, "b": 2}', f);
// {a: 11, b: 2}

In the above code, the second parameter of JSON.parse() is a function. If the key name is a, the function will add 10 to the key value.