reviver 必须手动判断 iso 日期字符串并转换为 date 实例,仅靠 typeof value === 'string' 会误转非日期字符串;需用正则匹配 /^\d{4}-\d{2}-\d{2}t\d{2}:\d{2}:\d{2}/ 并校验 new date().gettime() 有效性,且每次必须 return 值以避免 undefined。

JSON.parse 的 reviver 参数到底怎么写才生效
reviver 不是自动识别日期的魔法开关,它只负责逐个处理解析后的每个键值对。你必须自己判断哪些字符串长得像日期,再手动用 new Date() 转换。默认情况下,所有值都原样返回,不加干预就等于没写 reviver。
常见错误是把正则写成全局匹配(/^\d{4}-\d{2}-\d{2}T/),但 reviver 每次只传入一个 value,且原始 JSON 里日期通常已是 ISO 字符串(如 "2023-10-05T14:30:00.000Z"),直接比格式更稳:
JSON.parse(jsonStr, (key, value) => {
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) {
return new Date(value);
}
return value;
});
为什么不能只靠 typeof value === 'string' 就转
因为 JSON 里所有时间字段都是字符串,但不是所有字符串都是日期。比如 "id"、"email"、"2023-10"(年月)或 "2023/10/05"(非 ISO)都会误判。
- 只检查类型不检查格式,会把普通字符串也变成
Invalid Date - ISO 8601 格式最可靠:
YYYY-MM-DDTHH:mm:ss.sssZ或带时区偏移的变体 - 如果后端返回的是 Unix 时间戳数字(如
1696516200000),那得单独判断typeof value === 'number'并跳过字符串逻辑
reviver 中修改对象属性时要注意 key 的作用域
reviver 的 key 是当前遍历的属性名(根对象为 ""),value 是它的值。你不能在 reviver 里直接改原对象,所有转换必须通过 return 实现。返回值会替换该层级的值 —— 这意味着嵌套对象里的日期也能被递归处理,但你得确保逻辑覆盖到每一层。
典型陷阱:
- 写了
if (key === 'createdAt') { return new Date(value); }→ 只能捕获固定字段名,漏掉updatedAt、dateOfBirth等 - 在 reviver 里对
value做了value.setHours(...)→ 报错,因为此时value还是字符串,不是 Date 实例 - 忘记 return 原值 → 未匹配的字段会变成
undefined,整个数据结构被破坏
实际项目中建议封装成可复用函数
硬编码正则和 new Date() 在每个 JSON.parse 调用里重复写,既易错又难维护。抽成函数后还能统一处理无效日期(比如返回 null 而不是 Invalid Date):
const reviveDate = (key, value) => {
if (typeof value === 'string') {
const date = new Date(value);
if (!isNaN(date.getTime()) && value.match(/^\d{4}-\d{2}-\d{2}T/)) {
return date;
}
}
return value;
};
// 使用
const data = JSON.parse(jsonStr, reviveDate);
注意:Date 构造函数对某些非法字符串(如 "2023-02-30")也会静默返回 Invalid Date,所以必须配合 isNaN(date.getTime()) 校验。
真正麻烦的是混合格式——比如部分接口用 ISO,部分用秒级时间戳,部分用中文格式。这种时候 reviver 得叠加多条件判断,而不是指望一个正则通吃。











