Writing in the front

A few days ago, I almost lost my year-end bonus because of Json.stringify, which is about the application of json.stringify in engineering development where online users can’t submit forms. Because the string object after json. stringify in the field lacks a value key, the backend parse cannot correctly read the value, and then reports an exception to the interface system, and the user cannot proceed with the next action. This article will take a look at json.stringify in detail and take you through the process of writing your own json.stringify, taking a global look at your depth of understanding of various data types and handling extreme boundary cases.

JSON.stringify()

Json.stringify is one of the most commonly used methods on JSON objects in everyday development to convert a JavaScript object or value to a JSON string, optionally replacing the value if a replacer function is specified, Or the specified replacer is an array, optionally containing only the properties specified by the array.

In short, it is used to convert an object to a JSON string.

JSON.stringify(value[, replacer [, space]])
Copy the code
  • Value: specifies the JSON object to be serialized.
  • Replacer: This parameter is optional.
    • Function type: in the serialization process, each attribute of the serialized value is converted and processed by the function;
    • Array type: Only the property names contained in this array will be serialized into the final JSON string;
    • Null or not provided: All attributes of the object are serialized.
  • Space: An optional parameter that controls the spacing between strings.
    • Specifies a blank string for indentation, which is used to beautify the output (pretty-print).
    • The number type, which represents how many Spaces there are; The upper limit is 10. Less than 1 means no Spaces;
    • It is a string. If the string contains more than 10 characters, the first 10 characters are used as Spaces.
    • Null or not provided, there will be no Spaces.

Note:

  • Loop referenced objects (objects that refer to each other in an infinite loop) that execute this method throw an error.
  • Booleans, numbers, and string wrapper objects are automatically converted to their original values during serialization.
  • undefined, any function andsymbolValue is ignored during serialization (when present in an attribute value of a non-array object) or converted tonull(when appearing in an array). The function,undefined Returns when converted separatelyundefined, such asJSON.stringify(function(){}) or JSON.stringify(undefined). That’s why objects have properties of these types that can’t be used, rightJSON.parse(JSON.stringify())For deep copy.
  • 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.
const user = {name:"yichuan".age:18.university:"SCU"};
//1. Serialize objects
console.log(JSON.stringify(user));//'{"name":"yichuan","age":18,"university":"SCU"}'

//2. Serialize the base data type
console.log(JSON.stringify("Flat"));/ / "flat"
console.log(JSON.stringify(18));18 "/ /"
console.log(JSON.stringify(true));//"true"
console.log(JSON.stringify(null));//"null"
console.log(JSON.stringify(undefined));//undefined

//3. Use replacer
console.log(JSON.stringify(user,function(key,value){
   return typeof value === "number" ? Awesome! : "sixsixsix";
}));//'{name:"sixsixsix",age:666,university:"sixsixsix"}'

//4. Specify arrays
console.log(JSON.stringify(user,["name"]));//'{"name":"yichuan"}'

//5. Specify the spacing between strings
console.log(JSON.stringify(user,null.2));
/* { "name": "yichuan", "age": 18, "university": "SCU" } */

//6. Specify string spacing "*"
console.log(JSON.stringify(user,null."* * * * *"));
/*
{
*****"name": "yichuan",
*****"age": 18,
*****"university": "SCU"
}
*/
Copy the code

Collation and induction:

JSON.stringify The input The output
Underlying data types string string
number A string of type string
boolean “true”/”false”
undefined undefined
null “null”
NaN and Infinity “null”
symbol undefined
BigInt An error
Reference data type function undefined
Array includes function, undefined, and symbol string/”null”
regExp “{}”
Date Date toJSON() string
The common object
  • If there is a toJSON() method, serialize the return value of toJSON()
  • If function, undefined, and symbol are present in the attribute value, ignore them
  • All properties with symbol as the property key are completely ignored

|

Hand JSON. Stringify ()

In fact, it’s a bit of a hassle to rip the code by hand, considering all kinds of data processing, considering all kinds of boundary cases.

function stringify(data){
	const type = typeof data;
  // May be underlying data type processing
  if(type ! = ="object") {// Determine whether it is NaN or Infinity or null
    if(Number.isNaN(data)||data===Infinity) {return "null";
    }
    // The judgment may be function, undefined, symbol types
    if(type === "function" || type === "undefined" || type === "symbol") {return undefined
    }
    // Determine string or numeric processing
    if(type === "string" || type === "number") {return `"${data}"`
    }
    if (typeof data === 'bigint') {
      throw new TypeError('Do not know how to serialize a BigInt')}if (isCyclic(data)) {
      throw new TypeError('Converting circular structure to JSON')}return String(data);
  }else{
  	//null
    if(type==="null") {return "null"
    }else if(data.toJSON && typeof data.toJSON === "function") {/ / recursion
    	return stringify(data.toJSON);
    }else if(Array.isArray(data)){
    	const arr = [];
      // There are many cases for array types
      data.forEach((item,index) = >{
      	// The judgment may be function, undefined, symbol types
        if(type === "function" || type === "undefined" || type === "symbol" ){
          arr[index] = "null"
        }else{ arr[index] = stringify(item); }}); result =`"${arr}"`;
      return arr.result.replace(/'/g."");
    }else{
    	// Common objects
      const arr = [];
      // Iterate over the object
      Object.keys(data).forEach((key) = >{
      	//key if symbol type is ignored
        if(data[key]! = ="symbol") {if(typeofdata[key]! = ="undefined" && typeofdata[key]! = ="function" && typeofdata[key]! = ="symbol"){
            arr.push(`"${key}":stringify(data[key])`); }}})return ` {${arr}} `.replace(/'/g.'"')}}}Copy the code

Refer to the article

  • MDN: json.stringify ()
  • I Almost Lost my Year-end Bonus because of Json.stringify

Write in the last

The most common application of json.stringify in our development is probably deep copying of shallow objects, that is, serialization. However, when we are doing hand-tearing code, we need to consider various boundary cases, which is more troublesome for us, as an interview is also a comprehensive survey of data types.