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 默认不支持 datetimedatebytes 等类型,遇到就抛 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 规范明确禁止 NaNInfinity-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?