我们在前端开发中,我们会经常使用 JSON.stringify()
来序列化对象,但JSON.stringify
方法除了了第一个参数外,还有其它参数可用,今天我们一起来看看这些参数是做啥的。
1. 格式化
默认的 JSON.stringify(object)
出来数据是一行字符串,这看起来很丑,如下所示:
const user = { name: '', age: 4, isAdmin: true, friends: ['隔壁老王', '隔壁小姐姐'], address: { city: '红珊瑚大宝剑', }, } console.log(JSON.stringify(user)) // {"name":"","age":4,"isAdmin":true,"friends":["隔壁老王","隔壁小姐姐"],"address":{"city":"红珊瑚大宝剑"}}
JSON.stringify
也有一个内置的格式化器!
console.log(JSON.stringify(user, null, 2)) const user = { "name": "", "age": 4, "isAdmin": true, "friends": [ "隔壁老王", "隔壁小姐姐" ], "address": { "city": "红珊瑚大宝剑" } }
(如果你想知道这个 null
是什么,我们以后再谈)。
在这个例子中,JSON 的格式化有 2 个空格的缩进。我们还可以指定一个自定义字符,用于缩进。
console.log(JSON.stringify(user, null, '【大脚】')) const user = { 【大脚】"name": "", 【大脚】"age": 4, 【大脚】"isAdmin": true, 【大脚】"friends": [ 【大脚】【大脚】"隔壁老王", 【大脚】【大脚】"隔壁小姐姐" 【大脚】], 【大脚】"address": { 【大脚】【大脚】"city": "红珊瑚大宝剑" 【大脚】} }
2. 在序列化的数据中隐藏某些属性
JSON.stringify
还有一个很少有人知道的第二个参数,称为 replacer
,是一个函数或数组,决定哪些数据要保留在输出中,哪些不要。
举例一,假如,我们想隐藏用户的密码字段,可以这么做:
const user = { name: '', password: '12345', age: 4 }; console.log(JSON.stringify(user, (key, value) => { if (key === 'password') { return } return value }))
输出:
{"name":"","age":4}
我们可以进一步重构:
function stripKeys (...keys) { return (key, value) => { if (keys.includes(key)) return return value } } const user = { name: '', password: '12345', age: 4, gender: '未知' }; console.log(JSON.stringify(user, stripKeys('password', 'gender')))
输出:
{"name":"","age":4}
你也可以传递一个数组:
const user = { name: '', password: '12345', age: 4 } console.log(JSON.stringify(user, ['name', 'age']))
输出:
{"name":"","age":4}
最酷的是这对数组也有效,假设有如下的数组:
const poetry = [ { name: '', content: [ '兴尽晚回舟,误入藕花深处。', '鬼畜,鬼畜,单身百年手速。', '起点太高,于是期待太多,奢求太过,所以永不满足。', ], tags: ['经典', '魔幻', '鬼才'], }, { name: '张家瑞', content: [ '君子无非就是有耐心的狼。', '信者,无需誓言,不信者,誓言亦无助。' ], tags: ['经典', '魔幻', '鬼才'], }, ]
由于诗太过美丽,我想出名,最后输出就想打出输出关于名字的字段,那么也可以使用 JSON.stringify
来做:
console.log(JSON.stringify(poetry, ['name']))
输出:
[{"name":""},{"name":"张家瑞"}]
Nice!
3. 使用 toJSON 来创建自定义输出格式
如果一个对象实现了 toJSON
函数,JSON.stringify
将使用它来串化数据。
考虑一下这个例子:
class Fraction { constructor(n, d) { this.numerator = n; this.denominator = d; } } console.log(JSON.stringify(new Fraction(1, 2)))
输出:
{"numerator":1,"denominator":2}
如果我们想让输出的结果是 1/2
,那要怎么做呢?实现 toJSON
方法。
class Fraction { constructor(n, d) { this.numerator = n; this.denominator = d; } toJSON() { return `${this.numerator}/${this.denominator}` } } console.log(JSON.stringify(new Fraction(1, 2)))
JSON.stringify
根据 toJSON
方法来解析,所以结果是 1/2
。
4. 恢复数据
继续上面的例子,如果我们想再次解析 JSON 时,分数会神奇被还原成原来的对象,这是不是很酷?我们可以这样做:
class Fraction { constructor(n, d) { this.numerator = n; this.denominator = d; } toJSON() { return `${this.numerator}/${this.denominator}` } static fromJSON(key, value) { if (typeof value === 'string') { const parts = value.split('/').map(Number); if (parts.length === 2) return new Fraction(parts); } return value; } } const fraction = new Fraction(1, 2); const stringified = JSON.stringify(fraction); console.log(stringified); // "1/2" const revived = JSON.parse(stringified, Fraction.fromJSON); console.log(revived); // Fraction { numerator: 1, denominator: 2 }
我们可以向 JSON.parse
传递第二个参数来指定一个 reviver
函数,reviver
的工作是将字符串化的数据 “恢复”到它的原始形式。在这里,我们传递了一个reviver
,它是 Fraction
类的静态方法 fromJSON
。
有趣的是:这个功能在内置的 Date 对象中使用。试着查一下 Date.prototype.toJSON
:
console.log(JSON.stringify(new Date())) //=> '"2022-03-11T05:56:30.869Z"'
为了恢复日期,我们可以使用 JSON.parse
。
function reviveDate(key, value) { const regex = /^d{4}-d{2}-d{2}Td{2}:d{2}:d{2}(.d{1,}|)Z$/; if (typeof value === "string" && regex.test(value)) { return new Date(value); } return value; } console.log(JSON.parse('"2022-03-11T05:56:30.869Z"', reviveDate)) //=> Fri Mar 11 2022 13:56:30 GMT+0800 (中国标准时间)
5.使用 revivers 隐藏数据
与stringify
一样,parse
也可以用来隐藏数据。它们工作方式是一样的:
const user = JSON.stringify({ name: '', password: '12345', age: 4, }) console.log( JSON.parse(user, (key, value) => { if (key === 'password') return return value }) )
输出:
{ name: '', age: 4 }
结语
以上就是分享的关于 JavaScript 中JSON.stringify
方法处理 JSON 的相关技巧,希望对大家有用,如果你有更多关于 JSON 技巧的方法,欢迎留言讨论。