python类实例不能直接用json序列化,因其仅支持内置类型;pickle虽可直接序列化绝大多数实例,但仅限python环境且存在安全风险。

Python 类实例不能直接用 json 序列化,除非你主动控制其结构;而 pickle 能直接序列化绝大多数实例,但只适用于 Python 环境内可信数据交换。
为什么 json.dumps(obj) 会报 TypeError: Object of type XXX is not JSON serializable
因为 json 模块只认内置类型(dict、list、str、int、float、bool、None),不理解自定义类的结构。它不会自动调用 __dict__ 或任何方法来推导可序列化形式。
- 常见错误:直接传入一个
User(name="Alice", age=30)实例给json.dumps() - 可行解法:手动转成字典,例如
json.dumps(obj.__dict__)—— 但要注意__dict__不包含属性(property)、不包含父类未显式赋值的字段、也不处理循环引用 - 更稳妥的方式是定义
to_dict()方法或继承json.JSONEncoder并重写default()
用 pickle 保存和恢复实例最简路径
pickle 是 Python 原生序列化协议,能直接处理函数、类、模块引用和内存对象图(包括嵌套、循环引用)。但它生成的字节流无法被其他语言读取,且反序列化不受信数据有任意代码执行风险。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 保存:用
open("data.pkl", "wb")+pickle.dump(obj, f) - 恢复:用
open("data.pkl", "rb")+pickle.load(f) - 注意:被序列化的类定义必须在反序列化时的模块路径下可导入(即类不能是
__main__中临时定义的,否则报AttributeError: Can't get attribute 'XXX' on <module></module>) - 如果类有
__slots__,pickle默认支持;但若自定义了__getstate__/__setstate__,需确保逻辑正确,否则状态丢失
何时该选 json,何时必须用 pickle
选 json 当你需要跨语言、可读性强、只存简单数据结构(比如配置、API 返回体);选 pickle 当你要完整保留对象行为依赖(如绑定方法、闭包、非 POD 类型),且运行环境完全可控。
-
json:适合保存dataclass或NamedTuple的扁平数据,配合dataclasses.asdict()很干净 -
pickle:适合缓存训练好的sklearn模型、保存带回调函数的 GUI 对象、序列化协程状态等 - 性能上:
pickle(尤其是 protocol 5+)通常比json快,但体积不一定小;json文本可压缩性更好 - 兼容性陷阱:
pickle版本不兼容(如用 Python 3.12 的 pickle 写出的数据,在 3.9 上可能 load 失败),务必固定 protocol(如pickle.dump(obj, f, protocol=4))
真正容易被忽略的是:类名变更、模块移动、甚至只是把类从 foo.py 剪切到 bar.py,都会让旧的 pickle 文件失效——这不是 bug,是设计使然。而 json 虽安全,却要求你始终维护“对象 ↔ 字典”的映射契约,漏掉一个字段或类型转换错一次,加载时就静默丢数据。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










