前奏
JSON.stringify() 的使用大家肯定不陌生,一般在前端给后端传数据的时候用的多,但它隐藏的“秘密” 你知道多少呢,让我们一起来探索一下吧~。
JSON.stringify()
用于将 JavaScript
值转换为 JSON
字符串
语法
JSON.stringify(value[, replacer[, space]])
复制代码
参数
-
value
: 必须,通常是 JavaScript 值(通常为对象或者数组) -
replacer
: 可选。- 如果该参数是一个函数,则每个被序列化的值的每个属性都会被这个函数处理一遍
- 如果该参数是一个数组,则只有属性名在这个数组中的属性才会被序列化
-
space
: 可选。- 指定缩进的空白字符串,美化输出
- 如果该参数是一个数字,表示有多少个空格,上限为10,小于1则无空格
- space 也可以使用非数字,如:\t
- 如果是字符串,该字符串被作为空格。
返回值
一个表示给定值的 JSON
字符串。
基本使用
-
JSON.stringify() 可以转换对象或者值。(一般来说转换的是对象)
// 1、转换对象 JSON.stringify({ name: "xiaoqi", age: 20 }) // '{"name":"xiaoqi","age":20}' // 2、转换值 console.log(JSON.stringify(1)); // "1" console.log(JSON.stringify("xiaoqi")); // "xiaoqi" console.log(JSON.stringify(true)); // "true" console.log(JSON.stringify(null)); // "null" 复制代码
-
replacer 指定为函数,选择性的转换
JSON.stringify( { name: "xiaoqi", age: 20 }, (key, value) => { console.log(key, value, "->>>>>"); return value; } ) 复制代码
可以看到第一行输出的是原对象。当 replacer 是函数时,第一次参数不是对象的键值对,key 是空串,value是原对象。
利用函数的这个特性可以对打破 JSON.stringify() 本身的一些特性。
const obj = { name: "xiaoqi", age: undefined, special: Symbol("dcd"), hobby: () => "programming" }; console.log(JSON.stringify(obj)); // '{"name":"xiaoqi"}' console.log( JSON.stringify(obj, (key, value) => { const type = typeof value; switch (true) { case type === "undefined": return "undefined"; case type === "symbol": return value.toString(); case type === "function": return value.toString(); default: break; } return value; }) ); // '{"name":"xiaoqi","age":"undefined","special":"Symbol(dcd)","hobby":"function hobby() { return "programming"; }"} ' 复制代码
当后端需要前端为空值,'' 、null、undefined 时都不要传给后端时,也可以将replacer 设置为函数。
const obj = { name: "xiaoqi", age: undefined, height: null, text: "" }; console.log(JSON.stringify(obj, (key, value) => (!value ? undefined : value))); // '{"name":"xiaoqi"}' 复制代码
-
replacer 指定为数组时,相当于一个过滤器,可以转换指定的属性。
console.log( JSON.stringify( { name: "xiaoqi", age: 20 }, ["name"] ) ); // '{"name":"xiaoqi"}' 复制代码
-
使用第三个参数 space 来美化输出
JSON.stringify({ name: "xiaoqi", age: 20 }, null,'\t') /* '{ "name": "xiaoqi", "age": 20 }' */ 复制代码
特性
-
undefined
、函数、symbol
值在非数组对象中会被忽略。const obj = { name: "xiaoqi", age: undefined, special: Symbol("dcd"), hobby: () => "programming" }; console.log(JSON.stringify(obj)); // '{"name":"xiaoqi"}' 复制代码
-
undefined
、函数、symbol
值在数组中会被转换为null
。const obj = ["xiaoqi", undefined, Symbol("dcd"), () => "programming"]; console.log(JSON.stringify(obj)); // ["xiaoqi",null,null,null] 复制代码
-
undefined
、函数、symbol
值在单独转换是会被转换为undefined
。console.log(JSON.stringify(undefined)); // undefined console.log(JSON.stringify(Symbol("dcd"))); // undefined console.log(JSON.stringify(() => "programming")); // undefined 复制代码
-
布尔值、字符串、数字的包装对象会被转换为原始值。
// 包装对象 console.log(JSON.stringify([new Number(1), new Boolean(false), new String("112")])); // [1,false,"112"] 复制代码
-
所有以
symbol
值作为 key 的属性都会被忽略,即使在replacer
函数强制返回也不行。console.log(JSON.stringify({[Symbol("dcd")]: "xiaoxi" })); // '{}' console.log( JSON.stringify({ [Symbol("dcd")]: "xiaoxi" }, (key, value) => { if (typeof key === "symbol") { return value; } }) ); // undefined 复制代码
-
Date
对象会被转换为字符串console.log(JSON.stringify(new Date())); // "2021-12-07T02:40:07.609Z" 复制代码
-
RegExp
对象会被转换为{}
console.log(JSON.stringify(new RegExp())); // '{}' 复制代码
-
NaN、Infinity 、null
作为属性值都会被转换为null
。console.log(JSON.stringify({ name: null, age: NaN, height: Infinity })); // {"name":null,"age":null,"height":null} 复制代码
-
转换的值如果存在
toJSON
方法,toJSON 方法返回的值将成为最终转换的值console.log( JSON.stringify({ name: "xiaoqi", toJSON() { return "lalalla"; } }) ); 复制代码
-
对于对象来说,仅仅只序列化可枚举的的属性
const object1 = {}; Object.defineProperty(object1, "age", { value: 42, enumerable: false }); console.log(JSON.stringify(object1)); // '{}' 复制代码
-
循环引用的对象
const obj1 = [{](url) name: "xiaoqi" }; obj1.child = obj1; console.log(JSON.stringify(obj1)); // TypeError: Converting circular structure to JSON 复制代码
-
转换
BigInt
类型的值会报错console.log(JSON.stringify(BigInt(99999999999999))); // TypeError: Do not know how to serialize a BigInt 复制代码
异常处理
JSON.stringify 的使用容易出错,在工作中我们一般都会封装一个安全的 jsonStringify。
/**
* 对象转化为 JSON 格式字符串
*/
export const jsonStringify = (value: any) => {
try {
return JSON.stringify(value)
} catch (err) {
// 上报日志
sendLog('error', `[jsonStringify] error: ${err.message}`, 'js_error')
return "''"
}
}
复制代码
尾声
参考文章