json不支持方法、原型及特殊类型,映射转换需开发者手动介入:用reviver还原结构、replacer控制序列化、配合构造函数实现完整实例化,并注意类型丢失与边界情况。

JSON 本身是纯数据格式,不包含方法、原型或特殊类型(如 Date、RegExp、undefined、函数等),所以“映射转换”不是 JSON 自动完成的,而是靠开发者在 JSON.parse() 和 JSON.stringify() 的过程中,手动介入实现对象结构的还原或适配。
用 reviver 函数还原特定结构
JSON.parse() 的第二个参数 reviver 是一个回调函数,能在解析每个键值对时被调用,适合把普通 JSON 对象“升级”为带方法或特定原型的实例。
- 它接收两个参数:
key(当前字段名)和value(当前值) - 返回值将替代原 value;若返回
undefined,该属性会被忽略 - 常用于把时间字符串转成
Date实例,或把某类对象转成自定义类实例
例如:
基于三引擎设计,从微信文章、新闻和博客网页提取干净内容,支持标题作者日期元数据,多格式和批量处理。
const jsonStr = '{"name":"Alice","born":"2000-01-01T00:00:00Z"}';
const user = JSON.parse(jsonStr, (key, value) => {
if (key === 'born' && typeof value === 'string') {
return new Date(value);
}
return value;
});
// user.born 是 Date 实例,而非字符串
用 replacer 控制序列化输出结构
JSON.stringify() 的第二个参数 replacer 可以是数组(指定保留字段)或函数(定制每个字段的输出),用于控制哪些字段参与序列化,或对值做预处理。
- 函数形式:接收
key和value,返回要序列化的值 - 可过滤敏感字段(如
password)、格式化日期、跳过函数或 undefined - 注意:不能改变对象嵌套结构层级,但能替换值或返回
undefined删除字段
例如:
const user = {
name: 'Bob',
password: '123456',
createdAt: new Date('2023-01-01')
};
const json = JSON.stringify(user, (key, value) => {
if (key === 'password') return undefined; // 不序列化密码
if (value instanceof Date) return value.toISOString();
return value;
});
// → {"name":"Bob","createdAt":"2023-01-01T00:00:00.000Z"}
配合构造函数或工厂函数做完整映射
当需要严格还原为某个类的实例(含方法、私有状态等),仅靠 reviver 不够——因为它无法调用构造函数。推荐方式是先用 JSON.parse 得到 plain object,再传给构造函数或工厂函数初始化。
- 避免在
reviver中直接new MyClass(value),因为嵌套对象可能未完全解析完毕 - 更可靠的做法:解析后一次性构造,或使用静态
fromJSON()方法 - 类内部可定义序列化/反序列化逻辑,保持封装性
例如:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() { return `Hi, I'm ${this.name}`; }
static fromJSON(json) {
const obj = typeof json === 'string' ? JSON.parse(json) : json;
return new Person(obj.name, obj.age);
}
}
const person = Person.fromJSON('{"name":"Charlie","age":30}');
console.log(person.greet()); // "Hi, I'm Charlie"
注意边界情况和类型丢失
JSON 天然不支持以下内容,映射时需额外约定或处理:
-
null、number、string、boolean、array、object是唯一合法类型 -
undefined、function、Symbol、BigInt、Map、Set、RegExp在序列化时会被忽略、转空或报错 -
Date会变成字符串;NaN、Infinity变成null - 循环引用直接抛错,需提前清理或用第三方库(如
flatted)
若业务中频繁涉及复杂结构映射,建议封装统一的序列化/反序列化模块,并约定好类型标识字段(如 {"type": "date", "value": "..."}),提升可维护性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










