JavaScript中的JSON序列化与反序列化
字数 1076 2025-11-25 11:59:38
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() 的序列化过程
语法:
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进行数据交换。