在 JavaScript 开发中,把对象转换成 JSON 字符串是数据序列化里非常基础的操作。无论是前后端接口交互、浏览器本地缓存、日志记录,还是把内存中的数据结构保存为文本,都会频繁用到这种能力。对象本身是运行时的内存结构,而 JSON 字符串是标准文本格式,更容易在网络中传输,也更适合写入文件或数据库。理解对象转 JSON 字符串的常用方法,能够帮助开发者在数据格式转换时减少异常,也能让日志输出、接口调试和缓存读写更加稳定。

JSON.stringify 是对象转 JSON 字符串的核心方法
在 JavaScript 中,JSON.stringify 是最常用的内置序列化方法。它接收一个值,并返回符合 JSON 规范的字符串。对于普通对象、数组、数字、布尔值、字符串等值,都可以直接交给它处理。转换完成后,对象的属性名会被加上双引号,字符串值也会使用双引号包裹,数字和布尔值则保持 JSON 允许的形式。
下面这个例子展示了一个最基础的对象转换过程。对象中包含字符串、数字和布尔值,调用 JSON.stringify 后得到的结果是一段紧凑的 JSON 文本,可以直接用于接口请求体或缓存写入。
// 定义一个普通对象
const user = {
name: '张三',
age: 25,
isStudent: false
};
// 转换为 JSON 字符串
const jsonStr = JSON.stringify(user);
console.log(jsonStr);
// 输出: {"name":"张三","age":25,"isStudent":false}
除了普通对象,嵌套结构也可以被转换。数组会被转成 JSON 数组,对象中的对象会被转成嵌套对象。只要数据结构符合 JSON 可表示的范围,JSON.stringify 都能生成对应的字符串。需要注意的是,JSON 字符串并不是 JavaScript 对象字面量,它不能直接使用单引号,也不能保留注释。
// 定义包含数组和嵌套对象的数据
const payload = {
list: [
{ id: 1, title: '前端' },
{ id: 2, title: '后端' }
],
total: 2
};
console.log(JSON.stringify(payload));
// 输出: {"list":[{"id":1,"title":"前端"},{"id":2,"title":"后端"}],"total":2}
当转换结果需要还原为对象时,通常还会配合 JSON.parse 使用。序列化与反序列化是一对操作,前者把对象变成字符串,后者把字符串变回对象。在实际项目中,接口返回的数据往往就是 JSON 字符串,前端拿到后需要先解析成对象,再进行属性访问。
替换器与缩进参数让转换更可控
JSON.stringify 并不只有一个参数。它最多支持三个参数:第一个是待转换的值,第二个是替换器,第三个是缩进值。第二个参数可以是一个数组,也可以是一个函数。数组用于筛选需要保留的属性,函数则可以更灵活地修改属性名或属性值。第三个参数主要用于格式化输出,让生成的 JSON 字符串更易阅读。
当只需要导出对象中的部分字段时,使用数组形式的替换器非常方便。例如用户对象中包含姓名、年龄、地址和手机号,但日志中只想记录姓名和年龄,就可以把要保留的属性名传入数组。这样转换结果中只会出现指定字段,其他字段会被自动忽略。
const user = {
name: '张三',
age: 25,
address: '北京',
phone: '13800138000'
};
// 只保留 name 和 age 属性
const jsonStr = JSON.stringify(user, ['name', 'age']);
console.log(jsonStr);
// 输出: {"name":"张三","age":25}
函数形式的替换器适合做更细粒度的控制。它会在序列化过程中被逐个属性调用,开发者可以根据属性名或属性值返回新的值。比如把手机号做脱敏处理,把某些字段转换为统一格式,或者在特定条件下删除某个字段。相比数组筛选,函数替换器的表达能力更强,也更容易适配复杂业务。
const user = {
name: '张三',
age: 25,
phone: '13800138000'
};
// 对手机号做脱敏处理
const jsonStr = JSON.stringify(user, function (key, value) {
if (key === 'phone') {
return '138****8000';
}
return value;
});
console.log(jsonStr);
// 输出: {"name":"张三","age":25,"phone":"138****8000"}
第三个参数通常用于生成格式化的字符串。传入 null 和一个数字时,输出会使用指定数量的空格进行缩进。这种形式非常适合调试和日志输出,因为紧凑字符串在控制台里往往挤成一行,而格式化字符串能清晰展示层级关系。如果只想得到紧凑结果,可以不传第三个参数。
const user = {
name: '张三',
age: 25,
address: '北京'
};
// 使用 2 个空格缩进
console.log(JSON.stringify(user, null, 2));
// 输出:
// {
// "name": "张三",
// "age": 25,
// "address": "北京"
// }
特殊属性、循环引用与边界情况
并不是对象中的每一个属性都会出现在 JSON 字符串里。JSON.stringify 会忽略函数、undefined 和 Symbol 类型的属性,也不会转换原型链上的属性。这意味着如果对象里混入了方法、临时状态或符号键,序列化结果可能比原对象看起来更“少”。理解这些规则,可以避免在调试时误以为数据丢失。
const obj = {
name: '测试',
sayHello: function () {
console.log('hello');
},
age: undefined,
id: Symbol('id')
};
console.log(JSON.stringify(obj));
// 输出: {"name":"测试"}
还有一些常见类型有固定行为。Date 对象通常会被转换成 ISO 格式的日期字符串,RegExp 对象会被转换成空对象。如果对象上定义了 toJSON 方法,JSON.stringify 会优先调用该方法,并把返回结果作为该值的序列化依据。很多内置类型和自定义对象都依赖这个机制来控制自己的 JSON 表示。
Date对象会转换为字符串形式的日期。RegExp对象会转换为空对象。- 如果对象存在
toJSON方法,会优先使用它的返回值。 - 函数、
undefined、Symbol属性会被忽略。
循环引用是对象转 JSON 字符串时比较容易踩到的问题。如果一个对象直接或间接引用了自己,JSON.stringify 在递归处理时会不断深入,最终抛出错误。处理这类问题时,可以自定义替换器,用一个 WeakSet 记录已经访问过的对象。再次遇到同一个对象时,返回 null 或省略该属性,从而打断循环。
// 处理循环引用的示例
function handleCircular(obj) {
const seen = new WeakSet();
return JSON.stringify(obj, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return null;
}
seen.add(value);
}
return value;
});
}
const obj = {};
obj.self = obj;
console.log(handleCircular(obj));
// 输出: {"self":null}
上面示例中,遇到重复引用的对象时返回 null,因此循环字段最终显示为 null。如果希望字段完全消失,也可以返回 undefined,但要注意不同返回值会影响最终字符串结构。循环引用处理的核心不是改变 JSON.stringify 本身,而是在序列化过程中控制递归路径。
自定义转换方法与实用建议
如果只是为了理解序列化原理,也可以手写一个简单的对象转 JSON 字符串函数。递归函数会先判断当前值是否为对象,如果不是对象,则按原始值处理;如果是对象,就遍历自身属性,把每个键值对拼接成 JSON 片段。这种方式适合处理结构简单的普通对象,能帮助我们理解属性名、字符串引号和嵌套结构的生成过程。
// 简单版对象转 JSON 字符串,仅适合普通对象
function objToJson(obj) {
if (typeof obj !== 'object' || obj === null) {
if (typeof obj === 'string') {
return '"' + obj + '"';
}
return String(obj);
}
const parts = [];
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
parts.push('"' + key + '":' + objToJson(obj[key]));
}
}
return '{' + parts.join(',') + '}';
}
const user = {
name: '李四',
age: 30
};
console.log(objToJson(user));
// 输出: {"name":"李四","age":30}
自定义实现通常不会处理数组、日期、循环引用、特殊类型和复杂边界情况,因此在生产环境中仍然推荐使用 JSON.stringify。手写实现的价值更多在于学习,而不是替代原生方法。真实业务中,对象结构往往更复杂,原生方法在兼容性、性能和边界处理上更稳定。
在实际开发中,建议优先使用 JSON.stringify 完成对象转 JSON 字符串。需要筛选字段时使用数组替换器,需要修改值时使用函数替换器,需要阅读日志时使用缩进参数。遇到循环引用时,要结合 WeakSet 等结构做保护。同时要注意 JSON 字符串的规范:属性名和字符串值必须使用双引号,转换后的字符串是文本,不是可直接访问属性的对象。掌握这些方法后,数据序列化、接口传输和本地存储都会更加清晰可控。
JSON_stringifyjs对象json字符串对象序列化修改时间:2026-07-12 22:57:24