1. Introduction
()
Method to convert oneJavaScript
Convert an object or value to a JSON string if one is specifiedreplacer
Functions can optionally replace values, or the specified replacer is an array, then optionally only the attributes specified by the array.
grammar:
(value[, replacer [, space]])
parameter:
value
The value to be serialized into a JSON string.
replacer
Optional
- If this parameter is a function, during the serialization process, each attribute of the serialized value will be converted and processed by the function;
- If the parameter is an array, only the attribute names contained in this array will be serialized to the final JSON string;
- If the parameter is null or not provided, all properties of the object will be serialized.
space
Optional
- Specifies the blank string used for indentation to beautify output (pretty-print);
- If the parameter is a number, it represents how many spaces there are; the upper limit is 10.
- If this value is less than 1, it means there are no spaces;
- If the parameter is a string (when the string length exceeds 10 letters, take its first 10 letters), the string will be used as a space;
- If the parameter is not provided (or null), there will be no spaces.
Return value:
A JSON string representing the given value.
abnormal:
- When a loop reference is raised, the exception TypeError("cyclic object value") (loop object value)
- When trying to convert the value of type BigInt, TypeError("BigInt value can't be serialized in JSON") will be thrown (BigInt value cannot be serialized in JSON).
Basic use:
Notice:
- You can convert objects or values (usually used to convert objects more often)
- You can specify replacer to selectively replace function
- You can also specify replacer as an array to convert specified properties
Here is just the most basic explanation on MDN. Let’s first try these features
1. Convert objects
(({ name: 'Fat-headed fish', sex: 'boy' })) // '{"name":"Fat-headed fish","sex":"boy"}'
2. Convert normal value
(('Fat-headed fish')) // "Fat-headed fish"((1)) // "1" ((true)) // "true" ((null)) // "null"
3. Specify replacer function
(({ name: 'Fat-headed fish', sex: 'boy', age: 100 }, (key, value) => { return typeof value === 'number' ? undefined : value })) // '{"name":"Fat-headed fish","sex":"boy"}'
4. Specify an array
(({ name: 'Fat-headed fish', sex: 'boy', age: 100 }, [ 'name' ])) // '{"name":"Fat-headed fish"}'
5. Specify space (beautify output)
(({ name: 'Fat-headed fish', sex: 'boy', age: 100 })) // '{"name":"Fat-end fat-headed fish","sex":"boy","age":100}'(({ name: 'Fat-headed fish', sex: 'boy', age: 100 }, null , 2)) /* { "name": "Fat-headed fish", "sex": "boy", "age": 100 } */
2. 9 major features to remember
I used this method before, but I didn’t know his conversion rules in detail, and there were as many as 9.
Feature 1
undefined、any function andsymbolvalue,出现在非数组对象的属性value中时在序列化过程中会被忽略 undefined、any function andsymbolvalue出现在数组中时会被转换成 null。 undefined、any function andsymbolvalue被单独转换时,Will return undefined // 1. The existence of these three values in the object will be ignored(({ name: 'Fat-headed fish', sex: 'boy', // Functions will be ignored showName () { ('Fat-headed fish') }, // undefined will be ignored age: undefined, // Symbol will be ignored symbolName: Symbol('Fat-headed fish') })) // '{"name":"Fat-end fat-headed fish","sex":"boy"}' // 2. There are three values in the array that will be converted into null(([ 'Fat-headed fish', 'boy', // The function will be converted to null function showName () { ('Fat-headed fish') }, //Undefined will be converted to null undefined, //Symbol will be converted to null Symbol('Fat-headed fish') ])) // '["Fat-end fat-headed fish","boy",null,null,null]' // 3. The individual conversion will return undefined(( function showName () { ('Fat-headed fish') } )) // undefined ((undefined)) // undefined ((Symbol('Fat-headed fish'))) // undefined
Feature 2
The wrapping objects of Boolean values, numbers, and strings will be automatically converted to the corresponding original value during serialization.
(([new Number(1), new String("Fat-headed fish"), new Boolean(false)])) // '[1,"Fat-headed fish",false]'
Feature Three
All withsymbol
The attributes that are attribute keys will be completely ignored, even ifreplacer
These are mandatory in the parameter.
(({ [Symbol('Fat-headed fish')]: 'Fat-headed fish'} )) // '{}' (({ [ Symbol('Fat-headed fish') ]: 'Fat-headed fish', }, (key, value) => { if (typeof key === 'symbol') { return value } })) // undefined
Feature 4
NaN
andInfinity
The values and null of the format will be regarded as null.
(({ age: NaN, age2: Infinity, name: null })) // '{"age":null,"age2":null,"name":null}'
Feature Five
If there is a conversion valuetoJSON()
method, which defines what value will be serialized.
const toJSONObj = { name: 'Fat-headed fish', toJSON () { return '' } } ((toJSONObj)) // ""
Feature 6
Date date is calledtoJSON()
Convert it tostring
String (same()), therefore it will be processed as a string.
const d = new Date() (()) // 2021-10-05T14:01:23.932Z ((d)) // "2021-10-05T14:01:23.932Z"
Features 7
Performing this method on objects containing loop references (objects refer to each other, forming an infinite loop) will throw an error.
let cyclicObj = { name: 'Fat-headed fish', } = cyclicObj ((cyclicObj)) // Converting circular structure to JSON
Feature 8
Other types of objects, includingMap/Set/WeakMap/WeakSet
, only enumerable attributes will be serialized
let enumerableObj = {} (enumerableObj, { name: { value: 'Fat-headed fish', enumerable: true }, sex: { value: 'boy', enumerable: false }, }) ((enumerableObj)) // '{"name":"Fat-headed fish"}'
Feature Nine
When trying to convertBigInt
A value of type will throw an error
const alsoHuge = BigInt(9007199254740991) ((alsoHuge)) // TypeError: Do not know how to serialize a BigInt
3. Handwritten one
Finally finished learning againMany features! Let's handwritten a simple version based on these features (without replacer function and space)
Source code implementation:
const jsonstringify = (data) => { // Confirm whether an object has a circular reference const isCyclic = (obj) => { // Use Set data type to store detected objects let stackSet = new Set() let detected = false const detect = (obj) => { // If it is not an object type, you can skip it directly if (obj && typeof obj != 'object') { return } // When the object to be checked already exists in stackSet, it means that there is a circular reference if ((obj)) { return detected = true } // Save the current obj as stackSet (obj) for (let key in obj) { // Check the properties under obj one by one if ((key)) { detect(obj[key]) } } // After the level detection is completed, delete the current object to prevent misjudgment /* For example: The attributes of an object point to the same reference. If they are not deleted, they will be considered a circular reference. let tempObj = { name: 'Fat-headed fish' } let obj4 = { obj1: tempObj, obj2: tempObj } */ (obj) } detect(obj) return detected } // Features 7: // Perform this method on objects containing loop references (objects refer to each other, forming an infinite loop) and an error will be thrown. if (isCyclic(data)) { throw new TypeError('Converting circular structure to JSON') } // Feature Nine: // When trying to convert a value of type BigInt, an error will be thrown 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 getType = (s) => { return (s).replace(/\[object (.*?)\]/, '$1').toLowerCase() } // Non-object if (type !== 'object' || data === null) { let result = data // Feature 4: //NaN and Infinity formats and null will be regarded as null. if ([NaN, Infinity, null].includes(data)) { result = 'null' // Feature 1: // Undefined, arbitrary functions and symbol values are converted separately, undefined will be returned } else if ((type)) { // Get undefined directly, not a string 'undefined' return undefined } else if (type === 'string') { result = '"' + data + '"' } return String(result) } else if (type === 'object') { // Feature 5: // If there is a toJSON() method, the method defines what value will be serialized // Feature 6: // Date date calls toJSON() to convert it into a string string (same()), so it will be treated as a string. if (typeof === 'function') { return jsonstringify(()) } else if ((data)) { let result = ((it) => { // Feature 1: // `undefined`, `arbitrary function` and `symbol value` will be converted to `null` when appearing in the `array`. return (typeof it) ? 'null' : jsonstringify(it) }) return `[${result}]`.replace(/'/g, '"') } else { // Feature 2: // The wrapping objects of boolean values, numbers, and strings will be automatically converted to the corresponding original value during serialization. if (['boolean', 'number'].includes(getType(data))) { return String(data) } else if (getType(data) === 'string') { return '"' + data + '"' } else { let result = [] // Feature 8 // Other types of objects, including Map/Set/WeakMap/WeakSet, will only serialize enumerable properties (data).forEach((key) => { // Feature Three: // All attributes with symbol as the attribute key will be completely ignored, even if they are included in the replacer parameter. if (typeof key !== 'symbol') { const value = data[key] // Feature 1 // `undefined`, `arbitrary function` and `symbol value` will be ignored during serialization when appearing in the property value of `non-array object` if (!(typeof value)) { (`"${key}":${jsonstringify(value)}`) } } }) return `{${result}}`.replace(/'/, '"') } } } }
Test one:
// 1. Test the basic output(jsonstringify(undefined)) // undefined (jsonstringify(() => { })) // undefined (jsonstringify(Symbol('Fat-headed fish'))) // undefined (jsonstringify((NaN))) // null (jsonstringify((Infinity))) // null (jsonstringify((null))) // null (jsonstringify({ name: 'Fat-headed fish', toJSON() { return { name: 'Fat-headed fish 2', sex: 'boy' } } })) // {"name":"Fat-end 2","sex":"boy"} // 2. Compare with native conversion(jsonstringify(null) === (null)); // true (jsonstringify(undefined) === (undefined)); // true (jsonstringify(false) === (false)); // true (jsonstringify(NaN) === (NaN)); // true (jsonstringify(Infinity) === (Infinity)); // true let str = "Fat-headed fish"; (jsonstringify(str) === (str)); // true let reg = new RegExp("\w"); (jsonstringify(reg) === (reg)); // true let date = new Date(); (jsonstringify(date) === (date)); // true let sym = Symbol('Fat-headed fish'); (jsonstringify(sym) === (sym)); // true let array = [1, 2, 3]; (jsonstringify(array) === (array)); // true let obj = { name: 'Fat-headed fish', age: 18, attr: ['coding', 123], date: new Date(), uni: Symbol(2), sayHi: function () { ("hello world") }, info: { age: 16, intro: { money: undefined, job: null } }, pakingObj: { boolean: new Boolean(false), string: new String('Fat-headed fish'), number: new Number(1), } } (jsonstringify(obj) === (obj)) // true ((jsonstringify(obj))) // {"name":"Front-end fat head fish","age":18,"attr":["coding",123],"date":"2021-10-06T14:59:58.306Z","info":{"age":16,"intro":{"job":null}},"pakingObj":{"boolean":false,"string":"Front-end fat head fish","number":1}}((obj)) // {"name":"Front-end fat head fish","age":18,"attr":["coding",123],"date":"2021-10-06T14:59:58.306Z","info":{"age":16,"intro":{"job":null}},"pakingObj":{"boolean":false,"string":"Front-end fat head fish","number":1}} // 3. Test traversal objectslet enumerableObj = {} (enumerableObj, { name: { value: 'Fat-headed fish', enumerable: true }, sex: { value: 'boy', enumerable: false }, }) (jsonstringify(enumerableObj)) // {"name":"Fat-headed fish"} // 4. Test loop references and Bigint let obj1 = { a: 'aa' } let obj2 = { name: 'Fat-headed fish', a: obj1, b: obj1 } = obj2 (jsonstringify(obj2)) // TypeError: Converting circular structure to JSON (jsonStringify(BigInt(1))) // TypeError: Do not know how to serialize a BigInt
From the above test, we can see that jsonstringify is basically consistent with its performance.
This is the end of this article about the 9 major characteristics of learning and conversion rules. For more related content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!