JSON(JavaScript Object Notation)

张开发
2026/4/16 20:14:12 15 分钟阅读

分享文章

JSON(JavaScript Object Notation)
JSONJavaScript Object Notation是一种轻量级的数据交换格式。因为它脱胎于 JavaScript所以在 JS 中使用 JSON 非常自然和频繁。在 JS 中使用 JSON最核心的概念是区分**“JSON 字符串”**和“JS 对象”并掌握它们之间的相互转换以及相关的操作。一、 最核心的两个 API在浏览器环境和 Node.js 环境中JSON对象提供了两个静态方法这是 99% 的日常开发都会用到的1.JSON.parse(text[, reviver])—— 反序列化字符串转对象将 JSON 格式的字符串解析成 JS 的对象或数组。constjsonString{name: 张三, age: 25, isStudent: false, skills: [JS, Vue]};// 基础用法constuserObjJSON.parse(jsonString);console.log(userObj.name);// 输出: 张三console.log(typeofuserObj);// 输出: object// 进阶用法使用 reviver 函数转换器// 在解析过程中可以对解析出的值进行二次处理constparsedWithReviverJSON.parse(jsonString,(key,value){if(keyage){returnvalue1;// 把年龄加 1}returnvalue;});console.log(parsedWithReviver.age);// 输出: 262.JSON.stringify(value[, replacer[, space]])—— 序列化对象转字符串将 JS 的对象或数组转换成 JSON 格式的字符串。constuserObj{name:李四,age:30,password:123456,// 敏感信息girlfriend:null,skills:[React,Node]};// 基础用法constjsonStringJSON.stringify(userObj);// 输出: {name:李四,age:30,password:123456,girlfriend:null,skills:[React,Node]}// 进阶用法 1使用 replacer 数组只保留指定的字段常用于过滤敏感信息constsafeStringJSON.stringify(userObj,[name,age]);// 输出: {name:李四,age:30} (password 被过滤掉了)// 进阶用法 2使用 replacer 函数更精细的控制constcustomStringJSON.stringify(userObj,(key,value){if(keypassword){returnundefined;// 返回 undefined 会导致该属性被忽略}returnvalue;});// 进阶用法 3使用 space 参数格式化输出用于调试和美化constprettyStringJSON.stringify(userObj,null,2);/* 输出: { name: 李四, age: 30, password: 123456, girlfriend: null, skills: [ React, Node ] } */二、 必须注意的“坑”数据类型差异虽然 JSON 来源于 JS但它们并不完全等价。在parse和stringify时有以下类型差异需要注意JS 中的类型转成 JSON 字符串后的结果JSON 字符串转回 JS 的结果undefined被忽略丢失报错如果直接 parse “undefined”函数function被忽略丢失不存在Symbol被忽略丢失报错NaN,Infinity,-Infinity转成null解析为null不会变回 NaNDate对象调用toISOString()变成字符串变成普通字符串不再是 Date 对象RegExp对象变成普通空对象{}变成普通空对象{}null保持null保持null示例constobj{date:newDate(),fn:(){},undef:undefined,nan:NaN};console.log(JSON.stringify(obj));// 输出: {date:2023-10-25T08:00:00.000Z,nan:null}// fn 和 undef 直接消失了三、 经典高级技巧1. 深拷贝对象利用JSON方法是实现深拷贝最简单、最偷懒的方法但有局限性。constoriginal{a:1,b:{c:2}};constclonedJSON.parse(JSON.stringify(original));cloned.b.c999;console.log(original.b.c);// 依然是 2互不影响// ⚠️ 局限性不能拷贝 undefined、函数、Symbol、循环引用的对象会报错。2. 解决stringify无法处理undefined和函数的问题如果你想保留undefined可以通过toJSON方法自定义对象的序列化行为constobj{name:王五,age:undefined};// 给对象定义一个自定义的序列化方法obj.toJSONfunction(){return{name:this.name,age:this.ageundefined?null:this.age// 把 undefined 转成 null};};console.log(JSON.stringify(obj));// 输出: {name:王五,age:null}3. 处理循环引用对象相互引用会导致JSON.stringify报错。constobj{};obj.selfobj;// 循环引用// JSON.stringify(obj); // 直接报错TypeError: Converting circular structure to JSON// 解决方案自己写一个处理循环引用的方法或者使用第三方库如 lodash 的 cloneDeep四、 实际开发场景网络请求发请求发送 POST 请求时后端通常要求传 JSON 字符串。你需要用JSON.stringify(data)转换后放在 Request Body 里。收响应接收到后端的 Response 后通常是res.json()在 Fetch API 中这底层其实就是帮你调用了JSON.parse()。本地存储localStorage和sessionStorage只能存储字符串。存入localStorage.setItem(user, JSON.stringify(userObj))读取JSON.parse(localStorage.getItem(user))配置文件在前端工程化如 Webpack/Vite或 Node.js 中package.json、tsconfig.json等文件本身就是 JSON 格式读取时使用JSON.parse修改保存时使用JSON.stringify。五、 性能与安全提示性能对于超大型对象JSON.parse和JSON.stringify是同步操作且比较耗费 CPU可能会阻塞主线程导致页面卡顿。如果是极大对象可以考虑使用 Web Worker 在后台线程处理或者分块处理。安全绝对不要使用eval(( jsonString ))来解析 JSON这会导致严重的 XSS跨站脚本攻击漏洞。JSON.parse是安全且高效的它不会执行字符串中的任何代码。

更多文章