We use json.stringify in our everyday JSON conversion, but do you really know json.stringify?

Json.stringify is mostly used to convert it to a JSON string, but there are a lot of problems and confusion when using it, such as:

1) Why do some fields mysteriously disappear while converting JSON strings? 2) Why does the sequence of serialized strings change? 3) In what situations does json.stringify throw an error? 4) What will happen to the values of Date and enumeration? 5) What if you want to use json. stringify to specify indent whitespace and beautify the output? 6)…

Json.stringify is a new stringify.

JSON. Stringify syntax

JSON.stringify(value[, replacer [, space]])
Copy the code

parameter

Value Is the value to serialize to a JSON string

Replacer Optional function or array

Space Optional number of indent Spaces

Nine features of json.stringify

The first feature

Tags: boundary values For undefined, function, and symbol values, different structures return different results during serialization

var obj = {
  x: undefined.y: function() {}, 
  z: Symbol("")}JSON.stringify(obj);
/ / "{}"
Copy the code
  • Undefined, function, and symbol values are ignored in objects

So if they were an array element, what would be the result of serialization?

var arr = [
  undefined.function() {}, 
  Symbol("")]JSON.stringify(arr);
// "[null,null,null]"
Copy the code
  • Undefined, function, and symbol values are converted to NULL when they appear in an array

Again, what is the result of serialization when three elements are converted separately?

JSON.stringify(undefined);
// undefined

JSON.stringify(function() {});
// undefined

JSON.stringify(Symbol("1"));
// undefined

Copy the code
  • Undefined, function, and symbol values, which return undefined when converted separately

So let’s summarize the first and most noteworthy feature of json.stringify:

  • Undefined, function, and symbol values are ignored in objects
  • Undefined, function, and symbol values are converted to NULL when they appear in an array
  • Undefined, function, and symbol values, which return undefined when converted separately

Second feature

If there is a toJSON() method, what value does that method define to be serialized

var obj = {
  id: 1.name: 'Alan'.toJSON: function() {
    return "hello"}}JSON.stringify(obj);
// "\"hello\""

var obj = {
  id: 1.name: 'Alan'.address: {
    detail: 'xx'.country: 'xx'.toJSON: function() {
      return "hello"}}}JSON.stringify(obj);
// "{\"id\":1,\"name\":\"Alan\",\"address\":\"hello\"}"
Copy the code

Therefore, do not include the toJSON function in the object to be converted unless you really want to convert it in a certain scenario.

thinking

  • If toJSON returns a function, what should the output be?
var obj = {
  id: 1.name: 'Alan'.toJSON: function() {
    return function() { return 'test'}}}JSON.stringify(obj);
Copy the code

Combined with the first feature, interested students can try it out manually

Json.stringify’s second major feature:

  • Json.stringify will serialize directly using the toJSON() method if it has a toJSON() method in its properties

The third feature

Because of the first feature, some values in the key pair are ignored, so attributes of non-array objects are not guaranteed to appear in a serialized string in a particular order

var obj = {
  b: undefined.c: 'c'.d: function() {},
  e: 0.f: false.a: 1,}JSON.stringify(obj);
// "{\"c\":\"c\",\"e\":0,\"f\":false,\"a\":1}"
Copy the code

The order of the elements in the array is not affected because null is returned by default

Fourth feature

Tags: Objects

  • Booleans, numbers, and string wrapper objects are automatically converted to their original values during serialization
var arr = [
  new Number(1), new String("false"), new Boolean(false)]JSON.stringify(arr);
// "[1,\"false\",false]"
Copy the code

The fifth characteristic

Tags: cross-references, exceptions

  • Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error
var obj1 = {
  a: ' '
}
var obj2 = {
  b: obj1
}
obj1.a = obj2
JSON.stringify(obj1);
/** * Uncaught TypeError: Converting circular structure to JSON --> starting at object with constructor 'Object' | property 'a' -> object with constructor 'Object' --- property 'b' closes the circle */
Copy the code

Therefore, robust code typically adds a try… A catch prevents a program from crashing, which is typically seen in scenarios where deep copy is implemented using json.parse (json.stringify), because this circular reference is only seen in scenarios with deeper levels

Sixth feature

Label: symbol Ignored

  • All symbol key attributes are completely ignored, even if they are mandatory in the replacer parameter
var obj = {
  a: '1'[Symbol.for("foo")]: "foo",}JSON.stringify(obj, function(k, v) { 
  if (typeof k === "symbol") {return 'foo'
  }
  return v
});
// "{\"a\":\"1\"}"
Copy the code

The seventh feature

Tags: the Date

  • Date the Date is converted to a string by calling toJSON() (same as date.toisostring ()), so it is treated as a string
var obj = {
  time: new Date('2021-08-10'),}JSON.stringify(obj);
/ / "{\" time \ ": \" the 2021-08-10 T00:00:00. 000 z \ "}"
Copy the code

This is similar to the fourth feature

The eighth characteristic

Tag: NaN, Infinity

  • Values and nulls in NaN and Infinity formats are treated as null
var obj = {
  nan: NaN.ini: Infinity.n: null
}
JSON.stringify(obj);
// "{\"nan\":null,\"ini\":null,\"n\":null}"
Copy the code

The ninth feature

Tag: NaN, Infinity

  • Other types of objects, including Map/Set/WeakMap/WeakSet, serialize only enumerable properties, and non-enumerable values are ignored
var obj = {
  x: { value: 'x'.enumerable: false },
  y: { value: 'y'.enumerable: true}}var kk = Object.create(null, obj)
// kk = {y: "y", x: "x"}
JSON.stringify(kk);
// "{\"y\":\"y\"}"
Copy the code

Replacer parameter

Replacer can be an array or a function

As an array, the values of the array represent the properties to be serialized, that is, the values to be retained, and the others are ignored

var obj = {
  x: 'x'.y: 'y'.z: 'z'
}
JSON.stringify(obj, ['x'.'y']);
// "{\"x\":\"x\",\"y\":\"y\"}"
Copy the code

What if you specify a property that is ignored by default? Such as undefined

var obj = {
  x: 'x'.y: 'y'.z: 'z'.w: undefined
}
JSON.stringify(obj, ['x'.'y'.'w']);
// "{\"x\":\"x\",\"y\":\"y\"}"
Copy the code

Therefore, undefined will still be ignored, so we need to use function to transform

As a function, it takes two arguments, key and value, both of which are serialized

In plain English, let’s customize the json.stringify serialization function

var obj = {
  x: 'x'.y: 'y'.z: 'z'.w: undefined.a: 1.b: false
}
JSON.stringify(obj, function(k, v) {
  if (v === undefined) {
    return 'undefined'
  }
  return v
});
// "{\"x\":\"x\",\"y\":\"y\",\"z\":\"z\",\"w\":\"undefined\"}"
Copy the code

Space parameters

Space controls the indentation function for strings to beautify the JSON format. If it is a number, each level is indented more Spaces (up to 10 Spaces) than the previous level when stringing; If it is a string, each level indents the string (or the first 10 characters of the string) more than the previous level

There was a scenario where the back end returned a request to display the request data in a text entry box. Ask to beautify its format.

var respJSON = {"code":200."msg":"success"."data": {"total": 10."rows": []},"errors":null."status":200}
// Direct display will be very messy, as follows:
Copy the code

// You can use the third parameter to beautify
JSON.stringify(respJSON, null.'\t')
/ / or
JSON.stringify(respJSON, null.4)
Copy the code


JSON. Parse the grammar

JSON.parse(text[, reviver])
Copy the code

parameter

Text Specifies the string to be deserialized

Reviver Optional function converter, used to modify the original value generated by parsing before the return of the parse function

JSON parse characteristics

Tag: JSON specification

  • Parse () The JSON file must comply with the specifications. Do not end the file with a comma
JSON.parse("[1, 2],");
// Exception, comma ending

JSON.parse('{"a" : 1, }');
// Exception, comma ending

JSON.parse('{a: 1}');
// Exception, does not conform to JSON specification
Copy the code

Since json. parse is used to deserialize strings, it doesn’t have any special features. Instead, its second argument has some special features

Reviver features

The first feature

Tags: After specifying the reviver function sequentially, the value returned is parsed layer by layer, starting with the innermost attributes and working up to the top level. It’s kind of like the second half of the Onion model in KOA, parsing it from the inside out.

var objStr = "{\"b\":{\"c\":\"2\"}}"
JSON.parse(objStr, function(k, v) { 
  console.log(k); 
});
// c b ""
Copy the code
  • Start at the innermost layer and work your way up the hierarchy

Second feature

Tags: undefined

  • When reviver is specified, if undefined is returned, the current attribute is removed from the owning object
var objStr = "{\"a\":{\"aa\":1},\"b\":[null, null]}"
JSON.parse(objStr)
// { a: {aa: 1}, b: [null, null] }
JSON.parse(objStr, function(k, v) { 
  if (k === 'aa') {
    return undefined
  }
  if (v === null) {
    return undefined
  }
  return v
});
// {a: {}, b: []} note that the length of the b array is still 2
Copy the code

Even though the output array above is empty, the length is still 2. The element in B is empty, not null, not undefined, but empty, but the length is still occupied.

The third feature

Tag: Top layer

  • When iterating over the top-level value, the key value passed to the reviver function is an empty string “”, and the value value is the parsed value
var objStr = "{\"b\": 1}"
JSON.parse(objStr, function(k, v) { 
  console.log(k); 
});
// b ""
// There is no return value specified here, so the output is undefined
Copy the code

conclusion

Today’s focus is on JSON formats that we use on a daily basis, but JSON is not strictly a subset of javascript. We use json. stringify and json. parse every day, so we’ve seen a wave of json. stringify and json. parse and their respective features.

  • Nine features of json.stringify

    • Undefined, function, and symbol values are ignored in objects. Undefined, function, and symbol values are converted to NULL when they appear in an array. Undefined, function, and symbol values, which return undefined when converted separately

    • Json.stringify will serialize directly using the toJSON() method if it has a toJSON() method in its properties

    • Properties of non-array objects are not guaranteed to appear in a serialized string in a particular order

    • Booleans, numbers, and string wrapper objects are automatically converted to their original values during serialization

    • Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error

    • All symbol key attributes are completely ignored, even if they are mandatory in the replacer parameter

    • Date the Date is converted to a string by calling toJSON() (same as date.toisostring ()), so it is treated as a string

    • Values and nulls in NaN and Infinity formats are treated as null

    • Other types of objects, including Map/Set/WeakMap/WeakSet, serialize only enumerable properties, and non-enumerable values are ignored

  • JSON parse characteristics

    • Parse () The JSON file must comply with the specifications. Do not end the file with a comma

    • Reviver features

      • Start at the innermost layer and work your way up the hierarchy
      • If undefined is returned (or not returned) after the reviver function is specified, the current attribute is removed from the owning object
      • When iterating over the top-level value, the key value passed to the reviver function is an empty string “”, and the value value is the parsed value

Since json. stringify has a number of drawbacks, here’s a tool for converting JSON to serialize-javascript