返回
揭秘JSON.stringify()和JSON.parse()隐藏的陷阱
前端
2022-12-22 14:08:12
JSON.stringify() 和 JSON.parse():深入了解 JavaScript 的 JSON 操作 API
理解 JSON.stringify()
JSON.stringify() 是一个强大的 JavaScript API,可将对象转换为 JSON 字符串。然而,它并不是完全直观的。
想象一下您有一个包含姓名、年龄和工作函数的对象。您可能认为 JSON.stringify() 会将对象的所有属性转换为字符串,但事实并非如此。它只转换具有 toJSON()
方法的属性,其他属性会被忽略。
const obj = {
name: "John Doe",
age: 30,
job: () => "Software Engineer",
symbol: Symbol("secret")
};
const jsonStr = JSON.stringify(obj);
console.log(jsonStr); // {"name":"John Doe","age":30}
示例中,job
和 symbol
属性被忽略了。
JSON.stringify() 中的 toJSON() 方法
toJSON()
是一个特殊的函数,允许您自定义对象转换为 JSON 字符串的方式。当 JSON.stringify() 遇到具有 toJSON()
方法的对象时,它将使用该方法返回的值作为对象的 JSON 表示。
const obj = {
name: "John Doe",
age: 30,
toJSON: function() {
return {
name: this.name,
age: this.age,
salary: this.salary * 2
};
}
};
const jsonStr = JSON.stringify(obj);
console.log(jsonStr); // {"name":"John Doe","age":30,"salary":20000}
在示例中,toJSON()
方法将 salary
属性的值乘以 2,并将其添加到返回的对象中。
理解 JSON.parse()
JSON.parse() 用于从 JSON 字符串中解析数据。虽然通常很方便,但在某些情况下它可能会遇到问题。
如果 JSON 字符串包含无效的 JSON 数据或循环引用,JSON.parse() 可能会失败。
// 无效的 JSON 字符串
const jsonStr1 = "{name: "John Doe"}";
// 包含循环引用的 JSON 字符串
const obj = {
name: "John Doe",
age: 30,
self: obj
};
const jsonStr2 = JSON.stringify(obj);
try {
const obj1 = JSON.parse(jsonStr1);
console.log(obj1); // SyntaxError: Unexpected token n in JSON at position 1
} catch (err) {
console.error(err);
}
try {
const obj2 = JSON.parse(jsonStr2);
console.log(obj2); // TypeError: Converting circular structure to JSON
} catch (err) {
console.error(err);
}
示例中,jsonStr1
是无效的 JSON 字符串,jsonStr2
包含循环引用,导致 JSON.parse() 失败。
避免 JSON.stringify() 和 JSON.parse() 陷阱的技巧
- 确保对象的所有属性都具有
toJSON()
方法,或者使用replacer
参数指定要转换的属性。 - 在解析 JSON 字符串之前,请确保它是有效的,并且不包含循环引用。
- 小心处理日期、正则表达式和函数等特殊类型的数据。
常见问题解答
- 为什么我的对象属性在 JSON.stringify() 中被忽略了?
可能是因为这些属性没有toJSON()
方法。 - 如何将函数转换为 JSON 字符串?
您可以使用JSON.stringify()
的replacer
参数或自定义toJSON()
方法。 - 为什么 JSON.parse() 抛出一个错误?
JSON 字符串可能无效或包含循环引用。 - 如何避免 JSON.stringify() 中的循环引用?
使用toJSON()
方法来过滤循环引用或使用replacer
参数来跳过它们。 - JSON.stringify() 和 JSON.parse() 可以转换所有类型的 JavaScript 数据吗?
否,它们无法转换函数、符号和循环引用。