JSON(JavaScript Object Notation)是前后端数据交互中最常用的格式,无论是请求接口返回的数据,还是本地存储中的内容,几乎都以JSON形式存在。想在JavaScript中正确处理这些数据,核心就是掌握JSON.parse和JSON.stringify这两个方法。它们看起来简单,但实际使用中坑不少,比如解析报错Unexpected token、序列化时丢失数据、循环引用崩溃等。本文从基础用法讲到进阶技巧,帮你把JSON的解析与转换彻底搞明白。

JSON.parse:把字符串解析成JS对象
JSON.parse的作用是把一个符合JSON规范的字符串转换成JavaScript对象或数组。比如后端接口返回的数据通常是一段字符串,需要先解析才能像普通对象一样取值。基本用法如下:
const jsonStr = '{"name":"张三","age":25,"skills":["HTML","CSS","JS"]}';
const obj = JSON.parse(jsonStr);
console.log(obj.name); // 张三
console.log(obj.skills[2]); // JS这里要特别注意JSON字符串的规范:属性名必须用双引号包裹,字符串值也只能用双引号,不能出现单引号。下面这种写法会直接抛出语法错误:
// 错误示例:单引号不是合法的JSON格式
const badStr = "{'name':'张三'}";
JSON.parse(badStr); // SyntaxError: Unexpected token ' in JSON除了单引号问题,还有几个常见的报错场景:字符串末尾多了分号、值里包含未转义的双引号、传入了undefined或空字符串,以及从接口拿到的数据实际是HTML错误页(比如返回了一段<html>内容)却当作JSON去解析。遇到Unexpected token类错误时,建议先把原始字符串console.log出来检查,确认数据本身是否合法,再考虑解析。
JSON.parse还支持第二个参数reviver,它是一个函数,在返回结果前对每个键值做一次处理。常见用途是把日期字符串还原成Date对象,或者对某些字段做解密、类型转换:
const str = '{"name":"张三","birthday":"1998-06-15"}';
const user = JSON.parse(str, (key, value) => {
if (key === 'birthday') {
return new Date(value); // 转成Date对象
}
return value;
});
console.log(user.birthday.getFullYear()); // 1998JSON.stringify:把对象序列化成字符串
JSON.stringify做的是反向操作,把JS对象、数组转成JSON字符串,常用于向后台提交数据或存入localStorage。基础用法:
const obj = { name: '李四', age: 30, city: '北京' };
const str = JSON.stringify(obj);
console.log(str); // {"name":"李四","age":30,"city":"北京"}但有几个数据丢失的坑必须知道:undefined、函数、Symbol类型的值在序列化时会被直接忽略(出现在数组中则变成null);对象中值为undefined的属性直接消失;NaN和Infinity会被转成null;Date对象会变成ISO格式的字符串;Map和Set会被序列化成空对象{}。如果发现序列化后数据缺了一块,多半是踩了这些坑。
另外两个参数也很实用。第二个参数如果是数组,表示只保留指定的属性;如果是函数,可以自定义转换逻辑。第三个参数用于格式化输出,传数字表示缩进空格数,调试时打印出来的JSON会带换行和缩进,可读性大幅提升:
const obj = { name: '王五', age: 28, password: '123456' };
// 只序列化name和age,避免泄露密码
console.log(JSON.stringify(obj, ['name', 'age']));
// 格式化输出,缩进2个空格
console.log(JSON.stringify(obj, null, 2));
// 输出:
// {
// "name": "王五",
// "age": 28,
// "password": "123456"
// }还需要注意循环引用的问题:如果对象A的属性指向对象B,B又指回A,直接序列化会抛出TypeError: Converting circular structure to JSON。解决办法是在序列化前打断引用,或者用第二个参数函数把循环引用的值替换掉。
解析报错的容错处理与实用技巧
在真实项目中,接口返回的数据不一定总是合法JSON,直接调用JSON.parse可能导致整个页面报错。稳妥的做法是封装一层带try catch的解析函数:
function safeParse(str, fallback = null) {
if (typeof str !== 'string') return fallback;
try {
return JSON.parse(str);
} catch (e) {
console.warn('JSON解析失败:', e.message);
return fallback;
}
}
const result = safeParse(someUnknownData, []);
if (result) {
// 正常处理业务逻辑
}解析localStorage中的数据时尤其推荐这种写法,因为本地存储的内容可能被手动篡改或因版本更新结构变化,容错处理能避免程序直接崩溃。
最后介绍一个经典技巧:利用JSON.parse配合JSON.stringify实现对象深拷贝。原理是序列化时会生成一个全新的字符串,再解析回来就得到完全独立的对象:
const original = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(original));
copy.b.c = 99;
console.log(original.b.c); // 2,原对象不受影响不过这个方法有局限:函数、undefined、Symbol会丢失,Date会变成字符串,无法处理循环引用。如果对象结构复杂,还是建议使用结构化拷贝方案structuredClone,或者引入lodash的cloneDeep。掌握这些细节后,无论是接口数据处理、本地缓存还是数据调试,JSON相关的操作都能应对自如。
JSON解析JavaScriptJSON.stringify修改时间:2026-09-09 06:24:28