登录
首页 >  文章 >  python教程

Python json 序列化边界详解

时间:2026-05-12 22:39:48 319浏览 收藏

Python 的 `json` 模块序列化能力有明确的“安全边界”——仅原生支持 `None`、布尔值、数字、字符串、列表、元组及键为字符串的字典,而 `set`、`datetime`、`bytes`、自定义类等常见类型会直接抛出 `TypeError`;本文深入剖析这一边界的具体范围、典型报错场景,并系统介绍三种安全扩展方式:灵活的 `default` 参数、可复用的 `JSONEncoder` 子类继承,以及前置数据结构标准化(如 `dataclasses.asdict` 或 Pydantic 转换),同时揭示 `dict` 键类型限制、浮点精度陷阱、循环引用风险及 `NaN`/`Infinity` 的非标准处理等易被忽视的关键细节,助你写出健壮、兼容且可维护的 JSON 序列化代码。

Python json 模块的序列化边界

Python 的 json 模块不能直接序列化任意对象,它只支持有限的几种原生 Python 类型。所谓“序列化边界”,就是指哪些类型能被 json.dumps()json.dump() 安全处理,哪些会报错,以及如何在边界外安全扩展。

json 原生支持的类型(安全边界内)

以下类型可直接被 json 模块序列化,无需额外处理:

  • None → JSON null
  • boolTrue/False)→ JSON true/false
  • intfloat → 对应 JSON 数字(包括 inf-infnan 会被转为 null 或引发 ValueError,取决于 allow_nan 参数)
  • str → JSON 字符串(自动处理 Unicode、转义)
  • listtupledict(键必须是 str)→ JSON 数组和对象

常见不支持类型及典型错误

以下类型调用 json.dumps() 会直接抛出 TypeError

  • set:报 Object of type set is not JSON serializable
  • datetimedatetime:无法自动转字符串
  • bytesbytearray:需先解码为 str 或编码为 base64 字符串
  • 自定义类实例(如 class Person: pass):默认无 __dict__ 映射逻辑,也不触发任何转换
  • 函数模块typeellipsis (…) 等:完全不在序列化语义范围内

突破边界的常用方法

有三种主流方式在保持 json 标准兼容的前提下扩展序列化能力:

  • 使用 default 参数:传入一个 callable,当遇到不支持类型时,由它返回一个可序列化的替代值。例如:
    json.dumps(obj, default=lambda x: x.isoformat() if isinstance(x, datetime) else str(x))
  • 继承 json.JSONEncoder:重写 default() 方法,更清晰、可复用。适合项目中统一处理日期、枚举、自定义模型等。
  • 预处理数据结构:在调用 dumps 前,用递归或工具函数(如 dataclasses.asdict()pydantic.BaseModel.model_dump())将复杂对象转为 dict/list/str/int/float/None 组合。

特别注意的边界细节

有些行为看似“能过”,实则隐含风险:

  • dict 的 key 必须是 str:若传入 {1: "a", (1,2): "b"},会报错;{'1': "a", '(1, 2)': "b"} 才合法
  • 浮点精度丢失:JSON 规范不定义浮点精度,Python 默认用 repr() 级别输出,但某些极小或极大浮点数可能被科学计数法表示或截断
  • 循环引用json 模块不检测也不支持,会无限递归导致 RecursionError
  • NaN / Infinity:默认禁止(ValueError),开启 allow_nan=True 后会转为 null(非标准 JSON),部分解析器可能拒绝

以上就是《Python json 序列化边界详解》的详细内容,更多关于的资料请关注golang学习网公众号!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>