JSON.stringify() 的进阶用法:解锁你不曾了解的强大功能

更新日期: 2025-06-11 阅读: 563 标签: json

JSON.stringify() 是 JavaScript 开发中最常用的方法之一,但大多数开发者只停留在基础的数据序列化使用层面。实际上,这个方法隐藏了许多强大而实用的功能,能够解决开发中的各种实际问题。本文将深入探讨 JSON.stringify() 的进阶用法,帮助你写出更优雅、高效的代码


一、基础回顾:JSON.stringify() 的核心机制

在深入高级用法前,我们先明确 JSON.stringify() 的基本行为:

const user = {
  name: "fly63前端网",
  score: 89,
  secret: undefined,
  [Symbol('id')]: 123
};

console.log(JSON.stringify(user)); 
// 输出: '{"name":"fly63前端网","score":89}'

关键特性

  • 自动忽略 undefined、Symbol 和函数类型的属性

  • 只序列化对象自身的可枚举属性

  • 日期对象会被转换为 ISO 格式字符串

  • 循环引用会抛出错误


二、选择性序列化:第二个参数的妙用

1. 白名单过滤:精确控制输出字段

通过数组参数可以指定需要包含的属性列表:

const product = {
  id: 101,
  name: "无线耳机",
  price: 299,
  stock: 50,
  manufacturer: "Acme Corp"
};

// 只保留 id 和 name 字段
console.log(JSON.stringify(product, ['id', 'name'])); 
// 输出: '{"id":101,"name":"无线耳机"}'

实际应用场景

  • api 响应数据瘦身

  • 敏感信息过滤

  • 减少网络传输量

2. 转换函数:动态处理每个属性

更强大的方式是使用转换函数,它可以递归处理每个属性:

const employee = {
  name: "张三",
  salary: 15000,
  department: "研发部",
  joinDate: new Date('2020-06-15')
};

const result = JSON.stringify(employee, (key, value) => {
  if (key === 'salary') return undefined; // 隐藏薪资
  if (value instanceof Date) return value.toLocaleDateString();
  return value;
});

console.log(result);
// 输出: '{"name":"张三","department":"研发部","joinDate":"2020/6/15"}'

高级技巧

  • 实现自定义的序列化逻辑

  • 数据脱敏处理

  • 特殊类型(如 BigInt)的转换


三、美化输出:第三个参数的艺术

1. 数字缩进:标准格式化

const book = {
  title: "JavaScript高级程序设计",
  author: {
    name: "Nicholas C. Zakas",
    country: "美国"
  },
  tags: ["前端", "编程", "ES6"]
};

console.log(JSON.stringify(book, null, 2));

输出效果

{
  "title": "JavaScript高级程序设计",
  "author": {
    "name": "Nicholas C. Zakas",
    "country": "美国"
  },
  "tags": [
    "前端",
    "编程",
    "ES6"
  ]
}

2. 自定义缩进:个性展示

console.log(JSON.stringify(book, null, '-->'));

输出效果

{
-->"title": "JavaScript高级程序设计",
-->"author": {
--->"name": "Nicholas C. Zakas",
--->"country": "美国"
-->},
-->"tags": [
--->"前端",
--->"编程",
--->"ES6"
-->]
}

实用价值

  • 调试时更易读的输出

  • 生成文档中的示例数据

  • 保持团队代码风格统一


四、深度比较:对象指纹技术

1. 对象比较的痛点

const obj1 = { a: 1, b: 2, 1: "x" };
const obj2 = { b: 2, a: 1, 1: "x" };

console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // false

2. 键序问题的本质

JavaScript 对象键的顺序遵循特定规则:

  1. 数字键:按数值升序排列(0~2³²-1)

  2. 字符串键:按创建顺序排列

  3. Symbol键:不参与序列化

解决方案

function stableStringify(obj) {
  return JSON.stringify(obj, Object.keys(obj).sort());
}

console.log(stableStringify(obj1) === stableStringify(obj2)); // true

应用场景

  • 对象内容比对

  • 生成唯一缓存键

  • 数据一致性校验


五、特殊场景处理技巧

1. 处理循环引用

const circularObj = { a: 1 };
circularObj.self = circularObj;

// 直接序列化会报错
// JSON.stringify(circularObj); // TypeError

// 解决方案
const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) return '[Circular]';
      seen.add(value);
    }
    return value;
  };
};

console.log(JSON.stringify(circularObj, getCircularReplacer()));
// 输出: {"a":1,"self":"[Circular]"}

2. 自定义 toJSON 方法

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  toJSON() {
    return {
      fullName: `Mr./Ms. ${this.name}`,
      birthYear: new Date().getFullYear() - this.age
    };
  }
}

const p = new Person("李四", 30);
console.log(JSON.stringify(p));
// 输出: {"fullName":"Mr./Ms. 李四","birthYear":1993}


六、性能与安全考量

1. 性能优化

// 不好的做法:频繁序列化大对象
for (let i = 0; i < 1000; i++) {
  localStorage.setItem('data', JSON.stringify(largeObj));
}

// 优化方案:只序列化变化部分
let lastState;
function savePartial(state) {
  const changes = {};
  for (const key in state) {
    if (state[key] !== lastState?.[key]) {
      changes[key] = state[key];
    }
  }
  localStorage.setItem('changes', JSON.stringify(changes));
  lastState = {...state};
}

2. 安全注意事项

// 潜在XSS风险
const userInput = '{"__proto__": {"isAdmin": true}}';
const parsed = JSON.parse(userInput);
Object.assign({}, parsed); // 污染原型链

// 安全做法
const safeParse = (json) => {
  const parsed = JSON.parse(json);
  if (parsed && typeof parsed === 'object') {
    Object.setPrototypeOf(parsed, null);
  }
  return parsed;
};


七、实际应用案例

1. 深度克隆的局限与改进

// 基础深克隆
function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

// 增强版(处理特殊类型)
function enhancedDeepClone(obj) {
  return JSON.parse(JSON.stringify(obj, (key, value) => {
    if (typeof value === 'bigint') return value.toString() + 'n';
    if (value instanceof RegExp) return value.toString();
    return value;
  }));
}

2. 数据差异比较

function getObjectDiff(a, b) {
  const stableA = stableStringify(a);
  const stableB = stableStringify(b);
  
  if (stableA === stableB) return null;
  
  // 实际项目中可以使用更专业的diff算法
  return {
    before: JSON.parse(stableA),
    after: JSON.parse(stableB)
  };
}


结语

JSON.stringify() 远不止是一个简单的序列化工具,通过掌握它的高级用法,你可以:

  1. 更精准地控制数据输出

  2. 实现复杂对象的比较和克隆

  3. 提升调试和日志记录效率

  4. 处理各种边界情况和特殊需求

记住这些技巧,它们将在以下场景中发挥巨大价值:

  • API 开发与数据处理

  • 状态管理与持久化

  • 性能优化与调试

  • 安全数据处理

希望本文能帮助你重新认识这个看似简单却功能强大的方法,在实际开发中发挥它的最大潜力。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/12777

相关推荐

sublime 格式化Json

最近做数据匹配任务,需要生成很多json文件,但是每个json文件又太大,想要逐字段(key)检查,实在是太费眼,而且容易看错。因此每次生成的json文件,用sublime或者vscode将json数据格式化

为什么json 不能使用 int64类型

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集

js之map及转换json、Object

set map<=>object map转obj,因为map打印出来其实是数组里套长度为二的数组,和java的不同 Object.create(null)、Object.create({}),{}的不同创建对象的区别 第一个,默认是null对象,啥方法都没有、后两个一样继承了object类,有两个内置方法

解决IE8以下低版本实现JSON.parse()与JSON.stringify()的兼容

将字符串和json对象的相互转换,我们通常使用JSON.parse()与JSON.stringify()。解决IE8以下低版本实现JSON.parse()与JSON.stringify()的兼容呢:利用eval方式解析、new Function形式、自定义兼容json的方法、head头添加mate等

js实现json数据格式化及压缩

经常写代码就免不了与json这种轻量级的数据打交道,一般我们得到的json字符串是混乱的,计算机不在乎,再乱它都能认识,作为人类,虽然也能认识,但识读起来比较困难。

js实现json格式化,以及json校验工具的简单实现

这篇文章主要讲解:json结构及形式、json字符串转化为json对象【通过eval( ) 方法,new Function形式,使用全局的JSON对象】、json校验格式化工具简单实现

百度JSON LD结构化数据代码分享

百度JSON LD结构化数据代码分享,搞外贸网站,企业网站这么就,对谷歌的 schema 结构化数据比较熟悉,但是对百度的结构化数据就了解太少了

解析Json字符串的三种方法

在很多时候,我们的需要将类似 json 格式的字符串数据转为json,下面将介绍日常中使用的三种解析json字符串的方法

解决IE8下JSON.stringify()自动将中文转译成unicode的方法

在IE8下JSON.stringify()自动将中文转译为unicode编码,原本选择的中文字符,传到后台变为了unicode编码,即u****的形式。查找资料后发现,与标准的JSON.stringify()不同,IE8内置的JSON.stringify()会自动将编码从utf-8转为unicode编码,导致出现这种类似于乱码的情况。

JSON.parse 三种实现方式

近日在翻红宝书,看到 JSON 那一章节,忽然想到:“如何用 JS 实现 JSON.parse?”带着这个疑问,我找到了 JSON 之父 Douglas Crockford 写的 ployfill,里面提供了三种实现方式,下面我们逐一来分析。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!