Brief analysis of JSON.stringify & JSON.parse

There are many scenarios that used JSON before, but they haven't been studied carefully. In recent days, I took advantage of a requirement to sort out the relevant usage.

I. JSON.stringify()

1. Syntax JSON. Stringify (value [, replace [, space]])

2. Let's talk about the next two optional parameters

 

space: it is a blank string for specifying indentation, which is used to beautify the output. It can be a number or a string.

 1 const data = {
 2   a: 'bang',
 3   b: null,
 4   c: {
 5     x: 'xxx',
 6     y: 'yyy',
 7     z: 90
 8   },
 9   d: 9527
10 }
11 JSON.stringify(data, null, 4)
12 // {
13 //   "a": "bang",
14 //   "b": null,
15 //   "c": {
16 //       "x": "xxx",
17 //       "y": "yyy",
18 //       "z": 90
19 //   },
20 //   "d": 9527
21 // }
22 JSON.stringify(data, null, '-')
23 // {
24 // -"a": "bang",
25 // -"b": null,
26 // -"c": {
27 // --"x": "xxx",
28 // --"y": "yyy",
29 // --"z": 90
30 // -},
31 // -"d": 9527
32 // }

Replace: conversion rule, which can be a function or an array.

 1 // 1. array
 2 const data = {
 3   a: 'haha',
 4   b: 123,
 5   c: {
 6     d: 8080,
 7     e: null
 8   }
 9 };
10 JSON.stringify(data, ['b', 'd'])
11 // {"b":123}
12 JSON.stringify(data, ['a', 'c'])
13 // {"a":"haha","c":{}}
14 JSON.stringify(data, ['a', 'c', 'e'])
15 // {"a":"haha","c":{"e":null}}
 1 // 2. function
 2 const data = {
 3   a: 'haha',
 4   b: 123,
 5   c: {
 6     b: '123',
 7     d: 8080,
 8     e: null
 9   }
10 };
11 function rep (key, value) {
12   if (key === 'b' && typeof value === 'number') return ++value;
13   return value;
14 }
15 JSON.stringify(data, rep)
16 // {"a":"haha","b":124,"c":{"b":"123","d":8080,"e":null}}

3. value

The value to be serialized into a JSON string. There are some types that cannot be converted. undefined/function/symbol

  1). undefined

When JSON.stringify encounters undefined, it cannot be returned, but null is OK, so my treatment here is to convert undefined to null

The reason for this is because undefined == null //true, so the processed data does not affect the fuzzy judgment.

    2). function

It's also a type that can't be returned. My processing is to convert it to string type storage. One of the problems caused by this is that when JSON.parse is used, it needs to be converted to function again

 1 let data = {
 2   name: undefined,
 3   age: 18,
 4   type: null,
 5   fn: ()=>{
 6     return 999;
 7   }
 8 };
 9 let rep = (key, value) => {
10     if (value === undefined) {
11         return null;
12     }
13     if (typeof value === 'function') {
14         return Function.prototype.toString.call(value);
15     }
16     return value;
17 }
18 JSON.stringify(data, rep)
19 //{"name":null,"age":18,"type":null,"fn":"()=>{\n    return 999;\n  }"}

    3). symbol

es6 is a new data type, which is reserved for another article. Let's talk about JSON here.

 1 // When value yes Symbol Can be specified by the second parameter. If it is not specified, it cannot be returned
 2 // When key yes Symbol The second parameter cannot be specified
 3 let data={name: 'aaa', symbol: Symbol()};
 4 data[Symbol()] = 'bbb';
 5 JSON.stringify(data,(key,value)=>{
 6     console.log(key,value);
 7     // name aaa
 8     // symbol Symbol()
 9     if (typeof value === 'symbol') return 'symbol'; //Only specified here can return results
10     return value;
11 });
12 //{"name":"aaa","symbol":"symbol"}

If the value is Symbol, it can be converted by the second parameter; however, if the key is Symbol, it cannot be traversed and returned during traversal, similar to non enumeration type:

 1 let data = Object.create(null, {
 2   name: {
 3     value: 'aaa',
 4     enumerable: true
 5   },
 6   age: {
 7     value: 18,
 8     enumerable: false
 9   }
10 });
11 let a = JSON.stringify(data, (key, value) => {
12   console.log(key, value);
13   //name aaa
14   return value;
15 })
16 console.log(a);
17 //{"name":"aaa"}

 

2. JSON.parse()

1. Syntax: JSON.parse(text[, reviver])

2. Parameter: reviver converter. If this parameter (function) is passed in, it can be used to modify the original value generated by parsing. The call time is before the return of the parse function.

 1 let data = {
 2   name: undefined,
 3   age: 18,
 4   type: null,
 5   fn: () => {
 6     return 999;
 7   }
 8 };
 9 let rep = (key, value) => {
10     if (value === undefined) {
11         return null;
12     }
13     if (typeof value === 'function') {
14         return Function.prototype.toString.call(value);
15     }
16     return value;
17 }
18 let jsonS = JSON.stringify(data, rep);
19 //{"name":null,"age":18,"type":null,"fn":"()=>{\n    return 999;\n  }"}
20 let jsonR = JSON.parse(jsonS, (key, value)=>{
21   if (key) {
22     // return eval('('+value+')');
23     return new Function('return '+value)()
24   }
25   return value;
26 });
27 console.log(jsonR, jsonR.fn());
28 // { name: null, age: 18, type: null, fn: [Function] }
29 // 999

eval and new Function are used to deal with the reviver function. Because of the security problem of eval, it is not recommended to use the latter method first.

Three, toJSON

If there is a toJSON, this method will be executed before the second parameter when executing. stringify

toJSON is an override function, which should be used with caution.

 1 let data = {
 2   name: 'nan',
 3   age: 18,
 4   toJSON: function () {
 5     console.log('to');
 6     return this.name;
 7   }
 8 };
 9 JSON.stringify(data, (key,value)=>{
10   console.log('rep');
11   return value;
12 });
13 // to
14 // rep
15 // "nan"

 

Summary: only basic data types are stored in the object as far as possible, and the above types that are not friendly to data are avoided as far as possible.

Keywords: Javascript JSON

Added by macmonkey on Mon, 18 Nov 2019 10:48:59 +0200