By Tadm Link: juejin.cn/post/701885…

Basic knowledge of

The following information from MDN is relatively comprehensive and easy to understand

define

The json.stringify () method converts a JavaScript object or value to a JSON string, optionally replacing the value if a replacer function is specified, or optionally containing only the properties specified by the array if the specified replacer is an array.

grammar

Json.stringify (value[, replacer [, space]]) copies the codeCopy the code

parameter

value

The value to be serialized into a JSON string.

replacer optional

If the parameter is a function, each attribute of the serialized value is converted and processed by the function during serialization;

If the parameter is an array, only the property names contained in the array will be serialized into the final JSON string;

If this parameter is null or not provided, all attributes of the object are serialized.

space optional

Specifies a blank string for indentation, which is used to beautify the output (pretty-print).

If the argument is a number, it represents how many Spaces there are; The upper limit is 10. If the value is less than 1, there are no Spaces. If the parameter is a string (the first 10 characters are taken when the string is longer than 10 characters), the string will be used as a space.

If this parameter is not provided (or null), there will be no Spaces.

Value is commonly used. Replacers can be customized as required.

The return value

A JSON string representing the given value

abnormal

  • When inA circular referenceWill throw an exception TypeError (” Cyclic Object Value “)
  • When trying to switchBigIntType values will raise TypeError (“BigInt value can’t be serialized in JSON”).

features

Features a

1. Undefined, arbitrary functions, and symbol values are ignored during serialization (when they appear in property values of non-array objects) or converted to NULL (when they appear in arrays).

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

const obj = { a: 1, b: undefined, // ignore c: '11', d() { console.log('this is func'); }, // ignore e: Symbol('tadm') // ignore } console.log(JSON.stringify(obj)); // {"a":1,"c":"11"} console.log(JSON.stringify([1, '11', undefined, () => 1 + 1, Symbol('tadm')])); // [1,"11",null,null,null] Copies the codeCopy the code

3. Function/undefined returns undefined when converted separately

console.log(JSON.stringify(undefined)); // undefined console.log(JSON.stringify(() => 1 + 1)); // undefined copies the codeCopy the code

4.NaN and Infinity values and null are treated as null

console.log(JSON.stringify(NaN)); // null console.log(JSON.stringify(Infinity)); // null console.log(JSON.stringify(null)); // null copy codeCopy the code

Features two

If there is a toJSON() method, which defines what values will be serialized and ignores other attribute values

console.log(JSON.stringify({ name: 'toJSON', toJSON: () => console.log('this is toJSON') })); // this is toJSON console.log(JSON.stringify({ name: 'toJSON', toJSON: () => console.log('this is toJSON'), toJSON: () => 1 + 1,}); // 2 Copy the codeCopy the code

Features three

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

console.log(JSON.stringify(new Boolean(true))); // true console.log(JSON.stringify(new Number(1))); // 1 console.log(JSON.stringify(new String('tadm'))); // "tadm" copies the codeCopy the code

Features four

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

const obj = { a: 1, } obj.b = obj; console.log(JSON.stringify(obj)); // TypeError: Converting circular structure to JSON // --> starting at object with constructor 'Object' // --- property 'f' closes the Circle copy codeCopy the code

Features five

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

const date = new Date(); console.log(JSON.stringify(date), date.toISOString()); // "2021-10-14T07:34:10.112z" 2021-10-14T07:34:10.112z Copy codeCopy the code

Features 6

All properties with symbol as the property key are completely ignored, even if they are mandatory in the replacer parameter

Copy the codeCopy the code

Features seven

Other types of objects, including Map/Set/WeakMap/WeakSet, serialize only enumerable properties

const a = new Map(); a.set('x', 1); console.log(a, '------', JSON.stringify(a)); // Map(1) {'x' => 1} ------ {} const obj = object. create(null, {x: {value: 1}, y: {value: 1}) const obj = object. create(null, {x: {value: 1}, y: {value: 1}) 2, enumerable: true } }); console.log(Object.getOwnPropertyDescriptors(obj)); /** * { x: { value: 1, writable: false, enumerable: false, configurable: false }, y: { value: 2, writable: false, enumerable: true, configurable: false } } **/ console.log(JSON.stringify(obj)); // {"y":2} copy the codeCopy the code

Features eight

An error is also thrown when converting BigInt

Json.stringify (BigInt('666')) // Uncaught TypeError: Do not know how to serialize a BigInt copy codeCopy the code

Use the advanced

replacer

function

const foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 }; const replacer = (key, value) => { if (typeof value === "string") { return undefined; } return value; } console.log(JSON.stringify(foo, replacer)); // {"week":45,"month":7} Copy codeCopy the code

An array of

console.log(JSON.stringify(foo, ['foundation', 'transport'])); / / {" foundation ", "Mozilla", "transport" : "the car"} copy codeCopy the code

space

console.log(JSON.stringify(foo, null, 2)); / / show two Spaces / * * * {" foundation ":" Mozilla ", "model" : "box", "week" : 45, "transport" : "car", "month" : 7} * * / copy codeCopy the code

Source analysis

If you don’t call toString(), you’ll call toString()

implementation

const stringify = (data) => { const isCyclic = (obj) => { let set = new Set(); let flag = false; const deep = (obj) => { if (obj && typeof obj ! = 'object') { return; } if (set.has(obj)) { return flag = true; } set.add(obj); Fix object.create (null) if(! obj? .hasOwnProperty) { obj.hasOwnProperty = new Object().hasOwnProperty; } for (let key in obj) { if (obj.hasOwnProperty(key)) { deep(obj[key]); } // set. Delete (obj); } deep(obj); return flag; } if (isCyclic(data)) { throw new TypeError('Converting circular structure to JSON'); } if (typeof data === 'bigint') { throw new TypeError('Do not know how to serialize a BigInt'); } const type = typeof data; const commonKeys1 = ['undefined', 'function', 'symbol']; const commonKeys2 = [NaN, Infinity, null]; const getType = (s) => { return Object.prototype.toString.call(s).replace(/[object (.*?)] /, '$1').toLowerCase() }; if (type ! == 'object' || data === null) { let result = data; if (commonKeys2.includes(data)) { result = null; } else if (commonKeys1.includes(type)) { return undefined; } else if (type === 'string') { result = `"${data}"`; } return String(result); } else if (type === 'object') {if (typeof data.tojson === 'function') {if (typeof data.tojson === 'function') stringify(data.toJSON()); } else if (Array.isArray(data)) { let result = data.map((it) => { return commonKeys1.includes(typeof it) ? 'null' : stringify(it); }) return `[${result}]`.replace(/'/g, '"'); } else {// If ([' Boolean ', 'number'].includes(getType(data))) {return String(data); } else if (getType(data) === 'string') { return `"${data}"`; } else { let result = []; Keys (data). ForEach ((key) => {if (typeof key! == 'symbol') { const value = data[key]; if (! Commonkeys1.includes (typeof value)) {// note: If the value or the needs of the object type recursive processing result. Push (` "${key} : ${stringify (value)} `)}}}) return ` {${result}} `. Replace ('/' /, '"); }}}} Copy codeCopy the code

test

console.log(stringify({ toJSON: () => 1 + 1 })) // 2 const obj = { a: 1, b: undefined, c: '11', d() { console.log('this is func'); }, e: Symbol('tadm'), // g: BigInt('666') } // obj.f = obj; const obj = Object.create(null, { x: { value: 1 }, y: { value: 2, enumerable: true } }); console.log(stringify(obj)); // {"a":1,"c":"11"} // {"y":2} copy codeCopy the code

End

Json. stringify is just one of many apis that we use to manipulate objects, such as localStorage, because it can only store strings, we can just convert objects to strings. However, as mentioned above, it is easy to ignore the conversion results of non-normal data (undefined, null, BigInt, etc.), so be careful when using these features.