json.dumps() 默认无法序列化 datetime 对象,因其不符合 json 标准定义的六种类型;需通过 custom default 函数(如返回 isoformat() 字符串)实现可控转换,并在反序列化时手动还原。

Python 的 json 模块默认无法序列化 datetime 对象,直接调用 json.dumps() 会抛出 TypeError: Object of type datetime is not JSON serializable。
为什么 json.dumps() 会报错 datetime 不可序列化
JSON 标准只定义了 null、boolean、number、string、array、object 六种类型,datetime 不在其中。Python 的 json 模块严格遵循该标准,不会自动转换任何非标类型。
常见错误现象:
- 调用
json.dumps({'time': datetime.now()})立即崩溃 - 误以为设置
default=str就能“通用解决”——它确实能跑通,但生成的是形如'2024-05-22 14:30:15.123456'的字符串,丢失时区和类型语义,反序列化时无法还原为datetime
用 custom default 函数实现可控的 datetime 序列化
核心是传入 default 参数,让 json.dumps() 在遇到未知类型时调用你的函数做转换。关键在于:只处理 datetime(及 date、time),其他类型仍抛出原错误,避免掩盖真正的问题。
实操建议:
- 优先转为 ISO 8601 字符串:
dt.isoformat(),它天然支持时区(如+08:00)且可被datetime.fromisoformat()安全解析 - 若需兼容老系统或强制 UTC,先用
dt.astimezone(timezone.utc)归一化 - 不要用
strftime()自定义格式——除非业务强依赖某固定格式,否则增加解析负担
示例:
import json
from datetime import datetime, timezone
<p>def json_serializer(obj):
if isinstance(obj, datetime):
return obj.isoformat()
elif isinstance(obj, date):
return obj.isoformat()
raise TypeError(f"Object of type {type(obj).<strong>name</strong>} is not JSON serializable")</p><p>data = {"event": "login", "at": datetime.now(timezone.utc)}
json_str = json.dumps(data, default=json_serializer)</p><h1>输出类似:{"event": "login", "at": "2024-05-22T14:30:15.123456+00:00"}</h1><p></p>
反序列化时如何安全还原 datetime
json.loads() 不提供内置钩子来自动识别时间字符串,必须手动处理。不能依赖字段名硬编码(比如看到 "at" 就转 datetime),因为结构可能嵌套、字段名不固定。
推荐做法:
- 在序列化阶段就约定好时间字段的命名规范(如统一加
_at、_time后缀),反序列化时用递归函数扫描 key 名匹配 - 更健壮的方式:由业务层明确知道哪些字段是时间类型,在解析后单独调用
datetime.fromisoformat() - 警惕
fromisoformat()对带微秒/时区字符串的兼容性——Python 3.7+ 支持完整 ISO 格式,旧版本需用dateutil.parser.parse()
注意:json.loads() 的 object_hook 只接收 dict,无法感知字段原始类型,所以它适合做“键值对预处理”,不适合做类型推断。
用 dataclass + pydantic 更省心?
如果项目已引入 pydantic,直接用 BaseModel 是更优解:它内置了 datetime 的序列化/反序列化逻辑,支持配置 json_encoders 和自定义验证器,且类型提示清晰。
但纯 json 模块方案仍有价值:
- 轻量级脚本、无外部依赖要求
- 需要完全控制输出格式(如去掉微秒、强制 UTC 字符串)
- 与遗留系统对接,对方只认特定时间字符串格式
这时候,别绕开 default 参数,也别试图 monkey patch json.JSONEncoder——写个干净的小函数,显式传进去,最不容易出错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











