JSON.stringify() 和 JSON.parse() 默认不识别 Date 对象,序列化为 ISO 字符串后反序列化仍为字符串而非 Date 实例,需通过 reviver 函数或显式转换(如 new Date())安全还原,推荐 API 统一使用时间戳传输以避免歧义。

JavaScript 的 JSON.stringify() 和 JSON.parse() 默认不识别 Date 对象,直接序列化会变成字符串,反序列化后变回普通字符串而非 Date 实例——这是最常见的日期丢失类型陷阱。
JSON.stringify 会把 Date 变成 ISO 字符串
调用 JSON.stringify(new Date()) 得到的是类似 "2024-05-20T14:30:45.123Z" 的字符串,而不是对象或时间戳。这是因为 Date 对象在序列化前会隐式调用 toISOString() 方法,且该行为不可配置。
- 即使你自定义
toJSON()方法(如返回时间戳),也只影响当前 Date 实例,无法全局覆盖 - 嵌套对象中的 Date 字段同样被转为 ISO 字符串,容易在后续逻辑中误当作字符串处理
- 时区信息虽保留(UTC 格式),但若原始 Date 是本地时间,转换后可能与预期显示不符
JSON.parse 不会自动还原为 Date 对象
JSON.parse() 没有内置机制识别 ISO 时间字符串并转回 Date 实例。它只负责解析 JSON 结构,所有字段都保持原始类型——即字符串还是字符串。
- 常见错误:直接使用
obj.createdAt.getTime()报错TypeError: obj.createdAt.getTime is not a function - 手动 new Date(obj.createdAt) 虽可行,但需逐字段判断,易漏判或误判(比如把普通字符串当日期)
- 服务端返回的 ISO 字符串若未标注类型,前端很难安全区分哪些该转 Date,哪些不该
安全还原日期的实用方案
推荐在 JSON.parse() 时利用其第二个参数 reviver 函数统一处理:
立即学习“Java免费学习笔记(深入)”;
- 检查字段值是否为字符串且匹配 ISO 8601 格式(如 /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/)
- 尝试用
new Date(value)构造,再验证isNaN(date.getTime())排除非法字符串 - 对已知结构的 API 响应,更稳妥的做法是在解构时显式转换:
createdAt: new Date(data.createdAt)
避免陷阱的开发习惯
与其依赖运行时自动转换,不如从设计阶段就明确日期字段的传输约定:
- API 文档中标明哪些字段是日期,并约定统一用时间戳(number)而非字符串,减少歧义
- 前端封装请求层,在
fetch或 axios 的响应拦截器中批量转换日期字段 - 使用类库如
date-fns或dayjs时,注意它们的 parse 方法对输入格式敏感,不要直接传入未经校验的 JSON 字符串


















