Flask默认JSON序列化不支持datetime,需自定义JSONEncoder或手动转换:继承json.JSONEncoder重写default方法,用strftime格式化时间;或局部用json.dumps手动序列化并设ensure_ascii=False。

Flask默认JSON序列化不支持datetime对象
直接返回包含 datetime 或 date 的字典会报错:TypeError: Object of type datetime is not JSON serializable。Flask底层用的是Python标准库的 json 模块,它不认识时间类型,也不会自动调用 isoformat()。
重写 json.JSONEncoder 是最可控的方式
通过继承 json.JSONEncoder 并覆盖 default 方法,可以统一处理所有时间类型。注意:必须在创建 Flask 实例后,用 app.json_encoder(Flask 2.0+)或 app.json_encoder(旧版用 app.json_encoder)指定,不能只改全局 json.dumps。
- Flask 2.2+ 推荐用
app.json:设置app.json.encoder = CustomJSONEncoder -
default方法里优先判断isinstance(obj, datetime),再判断date,避免把timedelta等误转 - 输出格式建议用
obj.strftime('%Y-%m-%d %H:%M:%S')而非isoformat(),后者带毫秒和时区,前端解析容易出错
class CustomJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
if isinstance(obj, date):
return obj.strftime('%Y-%m-%d')
return super().default(obj)
<p>app.json.encoder = CustomJSONEncoder
</p>
用 @app.after_request 统一格式化响应体风险高
有人尝试在响应头已设为 application/json 后,用 after_request 解析并重序列化响应体。这不可靠:
- 响应体可能是流式生成(如
Response(streaming=True)),无法安全读取 - 已压缩的响应(
Gzip)会解码失败 - 第三方扩展(如
flask-restx)可能已自行处理过JSON,重复序列化导致嵌套字符串 - 性能损耗明显,每次响应都多一次
json.loads+json.dumps
更轻量的替代:用 json.dumps 手动序列化 + Response
适合局部控制,比如某个API只返回一个带时间的字典,不想影响全局行为:
- 先构造好数据字典,用自定义函数转换时间字段(如
dt.isoformat()或dt.strftime(...)) - 再用
json.dumps(data, ensure_ascii=False)序列化,避免中文变Unicode - 最后包装成
Response(..., mimetype='application/json') - 注意:别漏掉
ensure_ascii=False,否则中文变成\u4f60\u597d
from flask import Response
import json
<p>@app.route('/api/time')
def get_time():
data = {'now': datetime.now(), 'date': date.today()}</p><h1>手动转换</h1><pre class="brush:php;toolbar:false;">data['now'] = data['now'].strftime('%Y-%m-%d %H:%M:%S')
data['date'] = data['date'].strftime('%Y-%m-%d')
return Response(
json.dumps(data, ensure_ascii=False),
mimetype='application/json'
)
真正麻烦的不是怎么转格式,而是不同接口对时间精度、时区、可读性要求不一致——有的要秒级字符串,有的要毫秒时间戳,有的还要保留UTC标记。硬塞进一个全局 JSONEncoder 很容易后续踩坑。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











