导读:本期聚焦于梁博渊创作的《JavaScript如何解析和操作JSON数据?常用方法与实战技巧详解》,敬请观看详情。JSON是前后端数据交互中最常见的格式,掌握它的解析和操作方法是每个JavaScript开发者的基本功。本文围绕JSON.parse与JSON.stringify两个核心方法展开,讲解字符串与对象之间的相互转换、解析过程中的报错排查、深拷贝实现思路以及reviver和replacer参数的进阶用法,同时分析undefined、函数、循环引用等特殊情况的处理技巧,并对比JSON操作与普通对象操作的差异,帮助你避开实际开发中的常见坑。

JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,几乎贯穿了现代Web开发的每一个环节。无论是接口返回数据、本地存储还是配置文件,都离不开JSON的身影。JavaScript原生提供了两个核心方法来处理JSON:JSON.parse()负责把JSON字符串解析成JavaScript对象,JSON.stringify()负责把JavaScript对象序列化成JSON字符串。理解这两个方法的工作机制和边界情况,是用好JSON的关键。

JavaScript如何解析和操作JSON数据?常用方法与实战技巧详解

一、JSON字符串解析:JSON.parse的正确用法

从服务器拿到接口数据后,第一步通常就是解析。JSON.parse()接收一个JSON格式的字符串,返回对应的JavaScript值。最基本的用法非常简单:

const jsonStr = '{"name":"张三","age":25,"skills":["JS","CSS"]}';
const obj = JSON.parse(jsonStr);
console.log(obj.name);      // 张三
console.log(obj.skills[0]); // JS

这里有一个非常容易踩的坑:JSON字符串的键和字符串值必须使用双引号,不能用单引号。下面这段代码会直接抛出异常:

// 错误示范:单引号不是合法的JSON格式
try {
  const bad = JSON.parse("{'name':'张三'}");
} catch (e) {
  console.log(e.name); // SyntaxError
}

由于解析失败会抛出SyntaxError,在生产环境中建议始终用try...catch包裹解析逻辑,特别是在处理用户输入或第三方接口返回的数据时, malformed的JSON字符串如果处理不当,会导致后续代码全部中断执行。

JSON.parse()还支持第二个参数reviver(复活函数),可以在返回结果之前对每一个键值对做转换处理。这个功能常用于日期字符串还原成Date对象,或者对某些敏感字段做解密:

const str = '{"name":"李四","createTime":"2023-06-01T10:00:00Z"}';
const obj = JSON.parse(str, (key, value) => {
  if (key === 'createTime') {
    return new Date(value); // 把日期字符串还原为Date对象
  }
  return value;
});
console.log(obj.createTime.getFullYear()); // 2023

需要注意的是,reviver函数是自底向上执行的,也就是说最内层的属性会先被处理,最后处理的键是空字符串,对应的value是整个解析后的对象。如果reviver返回undefined,该属性会从结果对象中被删除。

二、对象序列化:JSON.stringify的细节与技巧

序列化方向的坑比解析更多一些。JSON.stringify()把JavaScript值转换成JSON字符串,但它并不是"什么都收"。有几类值在序列化时会被自动处理甚至丢弃:

  • undefined、函数、Symbol作为对象属性值时,序列化结果中该属性直接消失
  • undefined、函数、Symbol作为数组元素时,会被转换成null,以保证数组长度不变
  • NaNInfinity会被转换成null
  • Date对象会调用toJSON()方法,输出ISO格式的字符串
const data = {
  name: '王五',
  age: undefined,
  sayHi: function() { console.log('hi'); },
  birthday: new Date('1995-08-15'),
  scores: [98, undefined, 76]
};
console.log(JSON.stringify(data));
// {"name":"王五","birthday":"1995-08-15T00:00:00.000Z","scores":[98,null,76]}

第二个参数replacer非常有用,它可以是数组也可以是函数。传数组表示白名单,只保留指定的键;传函数则可以对每个值做定制化处理,比如隐藏密码字段:

const user = { name: '赵六', password: '123456', age: 30 };

// 白名单方式:只序列化name和age
const a = JSON.stringify(user, ['name', 'age']);

// 函数方式:过滤掉密码字段
const b = JSON.stringify(user, (key, value) => {
  if (key === 'password') return undefined; // 返回undefined即删除该字段
  return value;
});
console.log(a); // {"name":"赵六","age":30}
console.log(b); // {"name":"赵六","age":30}

第三个参数space用于格式化输出,传数字表示缩进的空格数,也可以传字符串作为缩进符。这在生成配置文件或调试时很实用,但要注意格式化后的字符串体积会明显变大,网络传输时不要加这个参数。

三、循环引用与深拷贝:进阶场景处理

当对象存在循环引用时,JSON.stringify()会直接抛出TypeError。这种情况在有双向关联的数据结构中很常见,比如树的子节点持有父节点引用:

const node = { id: 1 };
node.self = node; // 循环引用

try {
  JSON.stringify(node);
} catch (e) {
  console.log(e.message); // Converting circular structure to JSON
}

解决办法是利用replacer参数维护一个已访问对象的缓存,遇到重复访问就返回占位值:

function safeStringify(obj) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]'; // 标记循环引用
      seen.add(value);
    }
    return value;
  });
}

另一个经典应用是借助JSON.parse(JSON.stringify(obj))实现深拷贝。这个写法简单粗暴,但要清楚它的局限性:函数和undefined属性会丢失,Date会变成字符串,RegExp、Map、Set都会变成空对象{},无法处理循环引用。对于包含这些类型的复杂对象,还是应该使用结构化克隆structuredClone()或者递归克隆函数,或者引入lodash这类成熟的工具库。

在性能层面也要有意识:JSON的序列化和解析都是全量操作,数据量大时会成为性能瓶颈。高频场景下可以考虑只序列化需要的字段,或者在传输层换用更轻量的格式。另外,JSON.parse是同步阻塞的,解析超大JSON字符串(几MB以上)可能造成页面卡顿,必要可以把解析工作放到Web Worker中执行,避免阻塞主线程。

总结一下,JSON操作的核心就是parsestringify这一对方法,配合replacer和reviver两个参数能覆盖绝大多数定制化需求。日常开发中记住三点:解析一定要做异常捕获,序列化前想清楚特殊值会变成什么,深拷贝要确认数据类型是否被完整支持。把这些细节吃透,处理JSON数据时就能做到心里有底。

JSON解析JSON.stringifyJSON.parse修改时间:2026-09-13 01:38:29

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260913/55685.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。