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用户密码怎么加密_Laravel Hash门面使用教程
php增删改查怎么学_零基础入门php数据库操作必知基础【教程】
node.js报错:Cannot find module 'ejs'的解决办法
如何快速搭建FTP站点实现文件共享?
如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框
香港网站服务器数量如何影响SEO优化效果?
Java遍历集合的三种方式
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门
🚀拖拽式CMS建站能否实现高效与个性化并存?
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康
香港服务器如何优化才能显著提升网站加载速度?
高端云建站费用究竟需要多少预算?
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)
做企业网站制作流程,企业网站制作基本流程有哪些?
微信小程序 canvas开发实例及注意事项
高防服务器:AI智能防御DDoS攻击与数据安全保障
Laravel如何使用Passport实现OAuth2?(完整配置步骤)
在Oracle关闭情况下如何修改spfile的参数
IOS倒计时设置UIButton标题title的抖动问题
JavaScript如何实现错误处理_try...catch如何捕获异常?
Python高阶函数应用_函数作为参数说明【指导】
Laravel如何使用Vite进行前端资源打包?(配置示例)
iOS验证手机号的正则表达式
Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)
海南网站制作公司有哪些,海口网是哪家的?
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
Laravel storage目录权限问题_Laravel文件写入权限设置
Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
如何在阿里云服务器自主搭建网站?
JavaScript模板引擎Template.js使用详解
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
制作企业网站建设方案,怎样建设一个公司网站?
网站制作免费,什么网站能看正片电影?
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
如何在万网利用已有域名快速建站?
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案
网站制作大概多少钱一个,做一个平台网站大概多少钱?
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
Android中AutoCompleteTextView自动提示
如何快速搭建高效可靠的建站解决方案?
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?


