JavaScript 对象转 JSON 字符串:从 JSON.stringify() 到高级用法
在现代 Web 开发中,JavaScript 对象和 JSON(JavaScript Object Notation)字符串之间的转换是一项基础且至关重要的技能,当我们需要将数据发送到服务器、存储在 localStorage 中,或者进行序列化以便于传输时,都必须将一个 JS 对象转换成 JSON 格式的字符串。
幸运的是,JavaScript 提供了一个内置的、非常简单易用的方法来完成这项工作:JSON.stringify(),本文将探讨如何使用这个方法,并介绍一些实用的参数和高级技巧。
核心方法:JSON.stringify()
JSON.stringify() 是 JavaScript 的全局对象 JSON 上的一个静态方法,它可以将一个 JavaScript 对象或值转换为一个 JSON 字符串。
基本语法:
JSON.stringify(value, replacer, space)
value: 必需参数,将要被序列化为 JSON 字符串的 JavaScript 对象、数组、值等。replacer: 可选参数,可以是一个函数或一个数组,用于控制如何转换结果。space: 可选参数,一个数字或字符串,用于在结果 JSON 字符串中添加缩进和空格,使其更易于人类阅读。
一个最简单的例子:
假设我们有以下 JavaScript 对象:
const user = {
id: 101,
name: "张三",
email: "zhangsan@example.com",
isActive: true,
roles: ["admin", "editor"]
};
我们只需要将 user 对象传递给 JSON.stringify(),就能得到它的 JSON 字符串表示形式:
const jsonString = JSON.stringify(user); console.log(jsonString);
输出结果:
{"id":101,"name":"张三","email":"zhangsan@example.com","isActive":true,"roles":["admin","editor"]}
可以看到,原始的 JS 对象被成功转换了一个紧凑的、单行的 JSON 字符串,属性名被双引号包围,布尔值 true 和数组都被正确地表示。
可选参数详解
JSON.stringify() 的真正威力在于它的两个可选参数。
replacer 参数:定制化序列化过程
replacer 参数非常有用,它允许你决定哪些属性应该被包含在最终的 JSON 字符串中,以及如何转换它们的值。
replacer 是一个数组
如果你只想序列化对象中的特定属性,可以将一个包含这些属性名的数组作为 replacer。
const user = {
id: 101,
name: "张三",
password: "a-very-secret-password", // 我们不想序列化这个
email: "zhangsan@example.com"
};
// 只保留 name 和 email 属性
const safeJsonString = JSON.stringify(user, ["name", "email"]);
console.log(safeJsonString);
输出结果:
{"name":"张三","email":"zhangsan@example.com"}
password 字段被成功过滤掉了。
replacer 是一个函数
如果你需要更精细的控制,可以使用一个函数,这个函数会在序列化过程的每个属性上被调用,它接收两个参数:
key: 当前正在处理的属性名。value: 当前正在处理的属性值。
函数的返回值将作为最终的值被序列化,如果返回 undefined,则该属性会被从结果中移除。
示例:过滤掉敏感信息并修改值
const product = {
id: 'p-123', '无线蓝牙耳机',
price: 299,
internalSku: 'SKU-BT-2023-WHITE' // 内部编码,不希望对外暴露
};
const productJson = JSON.stringify(product, (key, value) => {
// 如果是内部编码,则返回 undefined,表示忽略该属性
if (key === 'internalSku') {
return undefined;
}
// 如果是价格,则打上人民币符号
if (key === 'price') {
return `¥${value}`;
}
// 其他情况,返回原值
return value;
});
console.log(productJson);
输出结果:
{"id":"p-123","title":"无线蓝牙耳机","price":"¥299"}
可以看到,internalSku 被移除了,而 price 的值被我们自定义的格式所替代。
space 参数:美化输出(Pretty-printing)
默认情况下,JSON.stringify() 生成的字符串是没有格式的,非常紧凑,这在数据传输时是高效的,但在调试或用于配置文件时,可读性很差。space 参数可以解决这个问题。
space是一个数字,它表示每一级缩进使用的空格数(最大为 10)。space是一个字符串(如'\t'或 ),它将使用该字符串作为缩进。
示例:美化输出
const user = {
id: 101,
name: "张三",
roles: ["admin", "editor"]
};
// 使用 2 个空格进行缩进
const prettyJsonString1 = JSON.stringify(user, null, 2);
console.log(prettyJsonString1);
// 使用制表符进行缩进
const prettyJsonString2 = JSON.stringify(user, null, '\t');
console.log(prettyJsonString2);
输出结果 (使用 2 个空格):
{
"id": 101,
"name": "张三",
"roles": [
"admin",
"editor"
]
}
重要注意事项
在使用 JSON.stringify() 时,有几个关键的“陷阱”需要了解。
循环引用
如果一个对象引用了自身(直接或间接),JSON.stringify() 会直接抛出 TypeError。
const circularObject = {};
circularObject.a = circularObject; // 对象引用了自身
try {
JSON.stringify(circularObject);
} catch (e) {
console.error(e); // TypeError: Converting circular structure to JSON
}
解决方案: 在序列化前,你需要手动处理循环引用,或者使用库(如 flatted 或 cycle)来安全地处理。
不被支持的 JS 类型
JSON.stringify() 无法处理所有 JavaScript 类型,以下类型的值在序列化时会被转换或忽略:
undefined: 会被忽略。Function: 会被忽略。Symbol: 会被忽略。BigInt: 会抛出TypeError。Map/Set: 会被忽略。
示例:
const data = {
name: "测试",
value: undefined,
sayHello: function() { console.log("Hello"); },
bigNum: 123n // BigInt
};
const result = JSON.stringify(data);
console.log(result); // 输出: {"name":"测试"}
可以看到,undefined、function 和 BigInt 都没有被包含在结果中。
对象的 toJSON() 方法
如果一个对象拥有一个名为 toJSON() 的方法,JSON.stringify() 在序列化时会优先调用这个方法,而不是直接序列化该对象本身。
示例:
const date = new Date();
// Date 对象内置了 toJSON() 方法
console.log(JSON.stringify(date)); // 输出类似 "2023-10-27T08:00:00.000Z"
// 我们也可以为自定义对象添加 toJSON
const event = { "技术分享会",
date: new Date(),
toJSON: function() {
return {
eventTitle: this.title,
happensOn: this.date.toISOString().split('T')[0] // 只取日期部分
};
}
};
console.log(JSON.stringify(event));
输出结果:
{"eventTitle":"技术分享会","happensOn":"2023-10-27"}
toJSON() 方法让你可以完全自定义对象如何被表示为 JSON。
JSON.stringify() 是 JavaScript 开发者工具箱中不可或缺的一员,它不仅简单易用,通过 replacer 和 space 参数,还能实现高度定制化的序列化需求。
| 场景 | 方法 |
|---|---|
| 基本转换 | JSON.stringify(obj) |
| 选择特定属性 | JSON.stringify(obj, ['prop1', 'prop2']) |
| 自定义属性值/过滤 | JSON.stringify(obj, (key, value) => { ... }) |
| 美化输出(调试用) | JSON.stringify(obj, null, 2) 或 `JSON.stringify(obj, null, |



还没有评论,来说两句吧...