JSON标准不支持Date对象,需用replacer函数将有效Date转为ISO字符串,再用reviver按字段名识别并还原为Date对象,同时校验时间有效性。

JSON 标准本身不支持 Date 对象,直接序列化会变成 null 或字符串 "Invalid Date"(取决于环境),所以必须手动干预。
使用 replacer 函数定制序列化行为
JSON.stringify() 的第二个参数 replacer 可以是函数,它会在每个键值对被序列化前调用,适合识别并转换 Date 实例。
- 检查值是否为
Date类型且有效(!isNaN(date.getTime())) - 返回
date.toISOString()—— 这是最通用、可解析的 ISO 8601 字符串格式(如"2024-05-20T08:30:00.000Z") - 其他类型原样返回,避免影响其他数据
示例:
const obj = {
name: "Alice",
createdAt: new Date("2024-05-20T08:30:00Z"),
count: 42
};
const json = JSON.stringify(obj, (key, value) => {
if (value instanceof Date && !isNaN(value.getTime())) {
return value.toISOString();
}
return value;
});
// 输出:{"name":"Alice","createdAt":"2024-05-20T08:30:00.000Z","count":42}
统一处理:封装成可复用的序列化函数
避免每次手动写 replacer,可以封装一个安全的 safeStringify 工具函数。
立即学习“Java免费学习笔记(深入)”;
- 内部使用相同的
Date判断逻辑 - 支持传入自定义
replacer并与日期处理逻辑合并(例如用typeof或Object.prototype.toString.call做更严格的类型判断) - 对
undefined、function、Symbol等非法 JSON 类型默认忽略(JSON.stringify本身已处理)
反序列化时还原为 Date 对象
仅序列化不够,从 JSON 解析回来时,字符串不会自动变回 Date。需在 JSON.parse() 的 reviver 中识别 ISO 时间字符串并重建。
- 匹配形如
^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$或带时区偏移的 ISO 字符串 - 用
new Date(str)构造,再验证有效性(!isNaN(date.getTime())) - 只对明确设计为时间字段的 key(如
"createdAt"、"updatedAt")做转换,避免误转普通字符串
示例(按字段名过滤):
const data = JSON.parse(json, (key, value) => {
if (['createdAt', 'updatedAt', 'expiresAt'].includes(key) &&
typeof value === 'string' &&
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) {
const date = new Date(value);
return isNaN(date.getTime()) ? value : date;
}
return value;
});
注意边界情况
不是所有时间字符串都该转成 Date,也不是所有 Date 都该无条件序列化。
-
new Date("")或new Date("invalid")会生成无效日期,toISOString()报错,务必先校验!isNaN(date.getTime()) - 如果后端期望的是毫秒时间戳(
date.getTime()),则替换为数字而非字符串,但需前后端约定一致 - 时区敏感场景下,
toISOString()总是输出 UTC 时间;若需本地时区格式,可用date.toLocaleString(),但会丢失时区信息,一般不推荐用于 API 传输


















