Python JSON 序列化的边界与坑点
发布时间 - 2026-01-31 00:00:00 点击率:次datetime等类型需用default参数处理,NaN/Infinity需allow_nan=False校验,中文需ensure_ascii=False,自定义类应实现to_dict方法。
datetime 对象直接 json.dumps 会报错
Python 的 json.dumps 默认不支持 datetime、date、bytes 等类型,遇到就抛 TypeError: Object of type datetime is not JSON serializable。
常见场景是数据库查询结果含时间字段,或日志结构里带 datetime.now(),一序列化就崩。
- 最轻量解法:用
default参数传处理函数,比如lambda obj: obj.isoformat() if isinstance(obj, (datetime, date)) els
e None
- 注意
default函数必须覆盖所有非标类型,否则仍报错;返回None会导致字段消失,不是万能兜底 -
datetime带时区(tzinfo)时,isoformat()输出含+08:00,但某些老系统只认 UTC 或无时区格式,得手动转成obj.astimezone(timezone.utc).isoformat()
NaN、Infinity 在 JSON 中非法但 Python 允许 float 表示
JSON 规范明确禁止 NaN、Infinity、-Infinity,但 Python 的 float 可以表示它们,json.dumps 默认会静默转成 null(不报错!),极易埋雷。
典型触发点:NumPy 计算结果、pandas DataFrame 含空值运算、除零后未检查。
- 用
allow_nan=False强制报错:json.dumps(data, allow_nan=False),这样能早暴露问题 - 如果必须保留语义,可预处理:遍历结构,把
math.isnan(x)或math.isinf(x)的值替换成字符串"NaN"或null,再序列化 - 注意
allow_nan是开关,不是转换器——设为False才真正校验,设为True(默认)反而放行非法值
中文字符被 \uXXXX 转义,前端显示乱码
默认情况下 json.dumps 会对非 ASCII 字符做 Unicode 转义,比如 "你好" 变成 "\u4f60\u597d",虽然合法,但可读性差,某些调试工具或旧版浏览器解析异常。
这不是 bug,是默认行为,源于早期对传输安全的保守设计。
- 加参数
ensure_ascii=False即可输出原生中文:json.dumps(data, ensure_ascii=False) - 但要注意 HTTP 响应头必须声明
Content-Type: application/json; charset=utf-8,否则前端可能按 latin-1 解码 - 若数据要写入文件,推荐显式指定编码:
with open("out.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False)
自定义类实例无法直接序列化
定义了 class User: 并创建实例后,直接 json.dumps(user) 会报 TypeError: Object of type User is not JSON serializable,哪怕它只有几个普通属性。
原因在于 json 模块不认识你的类,也不自动调用 __dict__——它只认内置类型和你显式告诉它的规则。
- 简单对象可用
default=lambda o: o.__dict__,但仅限于纯数据类,且不能有循环引用、不可序列化属性(如文件句柄) - 更稳的方式是让类实现
to_dict()方法,再在default中调用:default=lambda o: o.to_dict() if hasattr(o, "to_dict") else None - 别依赖
vars()或__dict__处理带 property、动态属性或私有字段的类,容易漏字段或暴露不该导出的内容
真正难的不是怎么序列化,而是怎么确保反序列化后还能还原语义——比如时间精度丢没丢、浮点误差有没有放大、空值是 null 还是 "null" 字符串。这些边界一旦跨过,debug 成本远高于加几行 default 函数。
# python
# js
# 前端
# json
# 编码
# 浏览器
# app
# 工具
# numpy
# pandas
# Float
# Object
# NULL
# if
# date
# math
# 字符串
# 循环
# Lambda
# class
# Property
# 对象
# default
# ASCII
# 数据库
# http
# bug
# 序列化
# 报错
# 设为
# 自定义
# 会报
# 转成
# 只认
# 也不
# 浮点
# 句柄
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
制作企业网站建设方案,怎样建设一个公司网站?
如何在建站宝盒中设置产品搜索功能?
Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
Android Socket接口实现即时通讯实例代码
如何在IIS中新建站点并解决端口绑定冲突?
香港服务器租用费用高吗?如何避免常见误区?
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
Python企业级消息系统教程_KafkaRabbitMQ高并发应用
Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】
Thinkphp 中 distinct 的用法解析
Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理
如何挑选高效建站主机与优质域名?
Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程
重庆市网站制作公司,重庆招聘网站哪个好?
Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)
再谈Python中的字符串与字符编码(推荐)
html文件怎么打开证书错误_https协议的html打开提示不安全【指南】
Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明
如何撰写建站申请书?关键要点有哪些?
Laravel storage目录权限问题_Laravel文件写入权限设置
Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】
如何用AWS免费套餐快速搭建高效网站?
如何在七牛云存储上搭建网站并设置自定义域名?
微信公众帐号开发教程之图文消息全攻略
Laravel如何实现用户密码重置功能?(完整流程代码)
bing浏览器学术搜索入口_bing学术文献检索地址
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
如何基于云服务器快速搭建个人网站?
黑客如何通过漏洞一步步攻陷网站服务器?
Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践
php485函数参数是什么意思_php485各参数详细说明【介绍】
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解
如何快速搭建高效可靠的建站解决方案?
海南网站制作公司有哪些,海口网是哪家的?
html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】
长沙做网站要多少钱,长沙国安网络怎么样?
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
如何快速生成可下载的建站源码工具?
*服务器网站为何频现安全漏洞?
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
佛山企业网站制作公司有哪些,沟通100网上服务官网?
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
进行网站优化必须要坚持的四大原则
nginx修改上传文件大小限制的方法


