JavaScript中的JSON序列化与反序列化
字数 1076 2025-11-25 11:59:38

JavaScript中的JSON序列化与反序列化

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在JavaScript中通过JSON.stringify()JSON.parse()实现序列化与反序列化。下面逐步讲解其核心概念、细节及常见问题。


1. JSON的基本规则

  • 支持的数据类型
    • 基本类型:stringnumberbooleannull
    • 复杂类型:ArrayObject(键必须是字符串)
  • 不支持的JavaScript特性
    • undefinedFunctionSymbolBigIntDateRegExpError等会被特殊处理或忽略。
    • 对象中的循环引用会报错。

2. JSON.stringify() 的序列化过程

语法

JSON.stringify(value, replacer?, space?)

步骤1:基本类型处理

  • 若值为基本类型,直接返回其JSON格式:
    JSON.stringify("hello")     // '"hello"'(字符串被双引号包裹)
    JSON.stringify(42)         // '42'
    JSON.stringify(null)        // 'null'
    JSON.stringify(undefined)   // undefined(注意:返回undefined而不是字符串)
    

步骤2:对象类型处理

  • 递归遍历属性
    const obj = { name: "Alice", age: 30 };
    JSON.stringify(obj); // '{"name":"Alice","age":30}'
    
  • 忽略不可序列化的值
    const obj = { func: () => {}, symbol: Symbol(), undefinedVal: undefined };
    JSON.stringify(obj); // '{}'(忽略函数、Symbol和undefined)
    

步骤3:replacer参数的自定义处理

  • 函数类型:对每个属性值进行转换,返回新值或undefined(忽略该属性):
    const obj = { a: 1, b: 2, c: undefined };
    JSON.stringify(obj, (key, value) => {
      if (key === "b") return undefined; // 忽略属性b
      return value; // 保留其他属性
    });
    // 结果:'{"a":1}'
    
  • 数组类型:指定仅序列化哪些属性:
    const obj = { a: 1, b: 2, c: 3 };
    JSON.stringify(obj, ["a", "c"]); // '{"a":1,"c":3}'
    

步骤4:space参数的格式化

  • 控制缩进(空格数或字符串):
    JSON.stringify({ a: 1 }, null, 2);
    // 结果:
    // {
    //   "a": 1
    // }
    

步骤5:处理特殊对象

  • toJSON()方法优先:若对象有toJSON方法,直接使用其返回值:
    const obj = {
      date: new Date("2023-01-01"),
      toJSON() { return { date: this.date.toISOString() }; }
    };
    JSON.stringify(obj); // '{"date":"2023-01-01T00:00:00.000Z"}'
    
  • Date对象默认转为字符串(因内置toJSON方法)。

3. JSON.parse() 的反序列化过程

语法

JSON.parse(text, reviver?)

步骤1:基本解析

  • 将JSON字符串转换为JavaScript值:
    JSON.parse('{"x": 1}'); // { x: 1 }
    

步骤2:reviver参数的后处理

  • 对每个属性值进行转换,类似replacer的逆过程:
    JSON.parse('{"a": 1, "b": 2}', (key, value) => {
      if (key === "b") return value * 10; // 修改属性b的值
      return value;
    });
    // 结果:{ a: 1, b: 20 }
    

4. 常见问题与解决方案

问题1:循环引用报错

const obj = { a: 1 };
obj.self = obj;
JSON.stringify(obj); // TypeError: Converting circular structure to JSON

解决:使用replacer跳过循环属性或第三方库(如flatted)。

问题2:丢失特殊类型(如Date)

const obj = { date: new Date() };
JSON.parse(JSON.stringify(obj)); // { date: "2023-01-01T00:00:00.000Z" }(Date变成字符串)

解决:在reviver中手动转换:

JSON.parse(JSON.stringify(obj), (key, value) => {
  if (key === "date") return new Date(value);
  return value;
});

问题3:性能优化

  • 避免序列化大型对象,可用replacer筛选必要属性。
  • 多次序列化相同结构时,可缓存replacer函数。

5. 总结

  • JSON.stringify()通过递归遍历、replacer过滤和toJSON方法控制输出。
  • JSON.parse()结合reviver可修复类型丢失问题。
  • 处理复杂场景(循环引用、特殊类型)需结合工具函数或自定义逻辑。

通过理解这些细节,可以更安全高效地使用JSON进行数据交换。

JavaScript中的JSON序列化与反序列化 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在JavaScript中通过 JSON.stringify() 和 JSON.parse() 实现序列化与反序列化。下面逐步讲解其核心概念、细节及常见问题。 1. JSON的基本规则 支持的数据类型 : 基本类型: string 、 number 、 boolean 、 null 复杂类型: Array 、 Object (键必须是字符串) 不支持的JavaScript特性 : undefined 、 Function 、 Symbol 、 BigInt 、 Date 、 RegExp 、 Error 等会被特殊处理或忽略。 对象中的循环引用会报错。 2. JSON.stringify() 的序列化过程 语法 : 步骤1:基本类型处理 若值为基本类型,直接返回其JSON格式: 步骤2:对象类型处理 递归遍历属性 : 忽略不可序列化的值 : 步骤3:replacer参数的自定义处理 函数类型 :对每个属性值进行转换,返回新值或 undefined (忽略该属性): 数组类型 :指定仅序列化哪些属性: 步骤4:space参数的格式化 控制缩进(空格数或字符串): 步骤5:处理特殊对象 toJSON()方法优先 :若对象有 toJSON 方法,直接使用其返回值: Date对象默认转为字符串 (因内置 toJSON 方法)。 3. JSON.parse() 的反序列化过程 语法 : 步骤1:基本解析 将JSON字符串转换为JavaScript值: 步骤2:reviver参数的后处理 对每个属性值进行转换,类似 replacer 的逆过程: 4. 常见问题与解决方案 问题1:循环引用报错 解决 :使用 replacer 跳过循环属性或第三方库(如 flatted )。 问题2:丢失特殊类型(如Date) 解决 :在 reviver 中手动转换: 问题3:性能优化 避免序列化大型对象,可用 replacer 筛选必要属性。 多次序列化相同结构时,可缓存 replacer 函数。 5. 总结 JSON.stringify() 通过递归遍历、 replacer 过滤和 toJSON 方法控制输出。 JSON.parse() 结合 reviver 可修复类型丢失问题。 处理复杂场景(循环引用、特殊类型)需结合工具函数或自定义逻辑。 通过理解这些细节,可以更安全高效地使用JSON进行数据交换。