Json.stringify is a function we often use in our daily development. For example, it can be used to process the body parameter in POST requests, store object objects in localStorage, or even implement a simple deep copy.
However, it is such a common JS official function, but there are some little people know the secret. Today, let’s find out.
Secret 1: Beautify the output
Many of you probably know this. Json.stringify takes a parameter to beautify the output and make it more readable.
By default, json.stringify prints the serialized result as a single line. But when a third argument, space, is provided, json.stringify takes a single line for each key and prefixes the key with space.
Space can be a number or a string.
const obj = { a: 1.b: { c: 2}}JSON.stringify(obj)
// "{"a":1,"b":{"c":2}}"
JSON.stringify(obj, null.2)
{/ /"
// "a": 1,
// "b": {
// "c": 2
/ /}
// }"
JSON.stringify(obj, null.'* *')
{/ /"
// **"a": 1,
// **"b": {
// ****"c": 2
/ / * *}
// }"
Copy the code
Secret 2: The magicreplacer
The second parameter is null. Don’t worry, just listen to me.
The second argument to json.stringify is called replacer. It can be a list or a function.
ifreplacer
Is a list of
When a replacer is a list, it acts like a whitelist, with the final result containing only the key in the list key: value.
const user = {
name: 'Hopsken'.website: 'https://hopsken.com'.password: 'SUPER_SECRET',}JSON.stringify(user, ['name'.'website'].2)
{/ /"
// "name": "Hopsken",
// "website": "https://hopsken.com"
// }"
Copy the code
It is worth noting that the key names in the final result are arranged in the order in which they are listed.
JSON.stringify(user, ['website'.'name'].2)
{/ /"
// "website": "https://hopsken.com",
// "name": "Hopsken"
// }"
// You can even do that
const config = { ... }
JSON.stringify(config, Object.keys(config).sort(), 2)
Copy the code
ifreplacer
Is the function
When replacer is a function, JS calls this function on each key-value pair during serialization and uses the return value of the function as the value corresponding to the key.
const obj = { a: 1.b: { c: 2}}JSON.stringify(obj, (key, value) => {
if (typeof value === 'number') {
return value + 1;
}
return value;
}, 2)
{/ /"
// "a": 2,
// "b": {
// "c": 3
/ /}
// }"
Copy the code
If the return value is undefined, the value is ignored in the final result. (This is expected behavior, since undefined is not a value in the JSON standard format).
const user = {
name: 'Hopsken'.password: 'SUPER_SECRET',}JSON.stringify(user, (key, value) => {
if (key.match(/password/i)) {
return undefined;
}
return value;
}, 2)
{/ /"
// "name": "Hopsken"
// }"
Copy the code
Secret 3: Self-control what needs to be output
Json.stringify’s third secret! When json.stringify () attempts to serialize an object, it first iterates over the object to see if it has the toJSON() property. If so, json.stringify () will serialize the value returned by this function instead of the original object.
Simply put, the toJSON() method defines what values will be serialized.
With the toJSON() method, we can control the behavior of json.stringify () ourselves.
Here’s an example:
const movie = {
title: 'Let the bullets fly'.year: 2010.stars: new Set([Chow Yun-fat.'I'.'ge you']),
toJSON() {
return {
name: `The ${this.title} The ${this.year}`.actors: [... this.stars]
}
}
}
JSON.stringify(movie, null.2)
{/ /"
// "name": "Let the bullets fly 2010",
// "actors": [
// "Chow Yun Fat ",
//
// ""
/ /]
// }"
Copy the code
In the example above, we used the toJSON property to enable json.stringify () to serialize Set data.
It’s worth noting that this in toJSON refers to objects at the current level and is scoped only to objects at the current level.
const user = {
name: 'Hospken'.wechat: {
name: 'FEMinutes',
toJSON() {
return `WX: The ${this.name}`; }}},JSON.stringify(user, null.2)
{/ /"
// "name": "Hospken",
// "wechat": "WX: FEMinutes"
// }"
Copy the code
As you can see, wechat. ToJSON () only applies to the wechat attribute.
Bonus: Use for listsJSON.stringify
?
So we know that the list in JS is also object. It stands to reason that json.stringify should also work on lists.
First, let’s try the default parameters.
const arr = ["apple"."orange"."banana"]
JSON.stringify(arr)
// "["apple","orange","banana"]"
Copy the code
Everything is normal.
Try the space argument again:
const arr = ["apple"."orange"."banana"]
JSON.stringify(arr, null.2)
/ /"
// "apple",
// "orange",
// "banana"
/ /"
Copy the code
Perfect!
The replacer?
const arr = ["apple"."orange"."banana"]
JSON.stringify(arr, (key, value) => {
return `one ${value}`
}, 2)
// ""one apple,orange,banana""
Copy the code
Cool cool, it seems not ok ah… It appears that the replacer function was executed only once, rather than the expected three times. However, json.stringify () is not intended to be used this way either, and unexpected results are normal.
But it doesn’t matter, we have toJSON()! Let’s try it:
const arr = ["apple"."orange"."banana"]
arr.toJSON = function() {
return this.slice().map(val= > `one ${val}`)}JSON.stringify(arr, null.2)
/ /"
// "apple",
// "orange",
// "banana"
/ /"
Copy the code
So we implement replacer via toJSON(). Isn’t it beautiful?
The end of the
So that’s the end of today’s mystery. We won’t go into the details of how json.stringify () handles boundary cases (such as circular references) because of space constraints.
Thanks for watching. See you next time
The resources
JSON.stringify() – MDN
ECMAScript 2015 (6th Edition, ECMA-262)
The 80/20 Guide to JSON.stringify in JavaScript
The secret power of JSON stringify