MEMEPh. ideas that are worth sharing...

Would you use JSON.stringify()

Foreword


JSON is a lightweight data format that can conveniently represent complex data structures. JSON objects have two methods: stringify() and parse(). In simple cases, these two methods can serialize JavaScript to JSON strings and parse JSON to native JavaScript values, respectively.

This article focuses on JSON.stringify()the usage and precautions.

 

1. How to use


1. Basic usage

JSON.stringify() A JavaScript object can be serialized into a JSON string.

let json1 = {
title: "Json.stringify",
author: [
"Riding in the Waves"
],
year: 2021
};
let jsonText = JSON.stringify(json1);

By default, JSON.stringify() will output a JSON string without spaces or indentation, so the value of jsonText looks like this:

"{"title":"Json.stringify","author":["boating in the waves"],"year":2021}"

When serializing JavaScript objects, all function and prototype members are intentionally omitted from the result. Also, undefined any properties with a value are skipped. What you end up with is a representation that all instance properties are valid JSON data types.

The JSON.stringify() method can accept a total of 3 parameters, two of which are optional (the second and third parameters respectively). These two optional parameters can be used to specify other ways of serializing JavaScript objects. The second parameter is a filter, which can be an array or a function; the third parameter is an option to indent the resulting JSON string . Use these parameters individually or in combination to gain more control over JSON serialization.

 

2. The second parameter -- filter

If the second parameter is an array, the JSON.stringify()returned result will only contain the object properties listed in the array. For example the following example:

let json1 = {
title: "Json.stringify",
author: [
"Riding in the Waves"
],
year: 2021,
like: 'frontend',
weixin: 'frontJS'
};
let jsonText = JSON.stringify(json1, ['weixin']);

In this example, the second parameter of the JSON.stringify() method is an array containing a string: "weixin". It corresponds to a property in the object to be serialized, so only this property will be included in the resulting JSON string:

"{"weixin":"frontJS"}"

If the second argument is a function, the behavior is different. The provided function accepts two parameters: the property name (key) and the property value (value). You can decide what operation to perform on the corresponding property based on this key. The key is always a string, except that it will be the empty string if the value does not belong to a key/value pair.

const students = [
  {
    name: 'james',
    score: 100,
  }, {
    name: 'jordon',
    score: 60,
  }, {
    name: 'kobe',
    score: 90,
  }
];



function replacer (key, value) {
  if (key === 'score') {
    if (value === 100) {
      return 'S';
    } else if (value >= 90) {
      return 'A';
    } else if (value >= 70) {
      return 'B';
    } else if (value >= 50) {
      return 'C';
    } else {
      return 'E';
    }
  }
  return value;
}
console.log(JSON.stringify(students, replacer, 4))

In the above code, we use replacer to replace the grade from the percentile scale to the grade level.

[
    {
    "name":"mem",
    "score":"S"
    },
    {
    "name":"ren",
    "score":"C"
    },
    {
    "name":"axon",
    "score":"A"
    }
]

 It is worth noting that if the second parameter of stringify is a function, if its return value is undefined, the corresponding property will not be serialized . If other values ​​are returned, the returned value will be used instead of the original value for serialization. change.

 

3. The third parameter -- string indentation

JSON.stringify() The third parameter of the method controls indentation and whitespace. When this parameter is a number, it indicates the number of spaces for each level of indentation. For example, to indent 4 spaces per level, you can do this:

let json1 = {
title: "Json.stringify",
author: [
"Riding in the Waves"
],
year: 2021
};
let jsonText = JSON.stringify(json1, null, 4);

The jsonText format obtained in this way is as follows:

{
"title": "Json.stringify",
"author": [
"boating in the waves"
],
"year": 2021
}

JSON.stringify() When processing data, data conversion and ease of reading are considered at the same time. However, ease of reading is often overlooked .

 

4. toJSON() method -- custom JSON serialization

Sometimes objects require JSON.stringify() custom JSON serialization on top of that . At this point, a method can be added to the object to be serialized, and the to JSON() appropriate JSON representation will be returned based on this method when serializing.

 

The following objects add a toJSON() method for custom serialization:

let json1 = {
title: "Json.stringify",
author: [
"Riding in the Waves"
],

year: 2021,
like: 'frontend',
weixin: 'frontJS',
toJSON: function () {
return this.author
} 
};
console.log(JSON.stringify(json1)); // ["boating in the waves"]

Note that arrow functions cannot be used to define the toJSON() method . The main reason is that the lexical scope of arrow functions is the global scope, which is not appropriate in this case.

 

2. Usage scenarios


1. Determine whether the array contains an object, or determine whether the objects are equal.

//Check if the array contains an object
let data = [
{name:'boating in the waves'},
{name:'frontend artisan'},
{name:'front-end development'},
],
val = {name:'boating in the waves'};
console.log(JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1);//true

We can also use JSON.stringify()methods to determine whether two objects are equal.

// Check if objects are equal
let obj1 = {
a: 1,
b: 2
} 

let obj2 = {
a: 1,
b: 2,
} 
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)) // true

However, this method has great limitations. If the object adjusts the order of the keys, it will judge wrong!

// After adjusting the position of the object key
let obj1 = {
a:1,
b:2
}

let obj2 = {
b: 2,
a: 1,
}
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)) // false

 

2. When using localStorage/sessionStorage

localStorage/sessionStorage By default, only strings can be stored. In actual development, we often need to store object types. At this time, we need to json.stringify() convert the object into a string when storing, and use the conversion back to the object when fetching the local cache json.parse().

// save data
function setLocalStorage(key,val) {
window.localStorage.setItem(key, JSON.stringify(val));
};

// get data
function getLocalStorage(key) {
let val = JSON.parse(window.localStorage.getItem(key));
return val;
};

// test
setLocalStorage('Test',['Front-end craftsman','boating in the waves']);
console.log(getLocalStorage('Test'));

 

3. Implement object deep copy

In development, sometimes we are afraid of affecting the original data. We often copy a piece of data for arbitrary operations. It is a good choice to use JSON.stringify() and to achieve deep copy.JSON.parse()

let arr1 = [1, 3, {
    username: ' kobe'
}];

let arr2 = JSON.parse(JSON.stringify(arr1));
arr2[2].username = 'duncan';
console.log(arr1, arr2)

This is to JSON.stringify convert the object into a JSON string, and then JSON.parse parse the string into an object. One by one, a new object is generated, and the new object will open up a new stack to achieve deep copying.

Although this method can achieve deep copying of arrays or objects, it cannot handle functions and regularities , because after the two are based on JSON.stringify sum JSON.parse processing, the obtained regularity is no longer regular (it becomes an empty object), and the obtained function is no longer function (become null).

let arr1 = [1, 3, function () { }, {
  username: ' kobe'
}];

let arr2 = JSON.parse(JSON.stringify(arr1));
arr2[3].username = 'duncan';
console.log(arr1, arr2)

 

3. Precautions for use

JSON.stringify() Although the function is very powerful, some attributes cannot be stringified, so the following situations should be paid attention to in the development to avoid some unexpected bugs.

 

1. There are NaN and Infinity in the converted value

let myObj = {
name: "boating in the waves",
age: Infinity,
money: NaN,
};

console.log(JSON.stringify(myObj));
// {"name":"boating in the waves","age":null,"money":null}


JSON.stringify([NaN, Infinity])
// [null,null]

 

2. There are undefined, arbitrary functions and symbol values ​​in the converted value

There are two cases:

JSON.stringify([undefined, function () { }, Symbol("")]);
// '[null,null,null]'
JSON.stringify({ x: undefined, y: function () { }, z: Symbol("") });
// '{}'

 

3. Circular references

If an object's property value points back to the object itself in some indirect way, then it is a circular reference. for example:

let bar = {
  a: {
    c: foo
  }
};
let foo = {
  b: bar
};
JSON.stringify(foo)

In this case, serialization will report an error:

// error message
Uncaught ReferenceError: foo is not defined
    at <anonymous>:3:8

 

4. When there are non-enumerable attribute values

Non-enumerable properties are ignored by default:

let personObj = Object.create(null, {
name: { value: "boating in the waves", enumerable: false },
year: { value: "2021", enumerable: true },
})
console.log(JSON.stringify(personObj)) // {"year":"2021"}

 

4. Summary


JSON.stringify() Used to serialize JavaScript objects to JSON strings, this method has options that can be used to change the default behavior to implement filtering or modification processes. However, it should also be noted that some properties cannot be stringified, so these pits should be avoided during development!