如何将含PyDantic模型的字典序列化为JSON(PyDantic v2+)
问题描述
给定一个结构任意的字典,其中混合了原生Python对象和PyDantic的BaseModel子类实例,示例如下:
my_dict = {"key1": "value1", "key2": {"key3": pydantic_object1, "key4": 4}, "key5": pydantic_object2}
需要将该字典转存为JSON文件。但直接用BaseModel.model_dump()把PyDantic对象转成字典后调用json.dump的方式不可行——因为PyDantic对象中的datetime、带自定义序列化器的对象等无法被Python原生JSON序列化器处理,同时也无法编写调用PyDantic内置JSON编码器的自定义编码器,请问在PyDantic v2及以上版本中该如何解决?
解决方案
方法1:递归使用model_dump_json处理嵌套对象
PyDantic v2的BaseModel提供的model_dump_json()方法会自动处理datetime、自定义序列化器等特殊类型。我们可以递归遍历字典,将遇到的PyDantic对象转换为JSON兼容的Python结构:
import json from pydantic import BaseModel def process_dict(obj): if isinstance(obj, BaseModel): # 先用model_dump_json完成PyDantic对象的序列化,再解析为Python字典 return json.loads(obj.model_dump_json()) elif isinstance(obj, dict): return {k: process_dict(v) for k, v in obj.items()} elif isinstance(obj, (list, tuple)): return [process_dict(item) for item in obj] else: # 原生Python对象直接返回(JSON可序列化类型) return obj # 处理目标字典 processed_data = process_dict(my_dict) # 写入JSON文件 with open("output.json", "w", encoding="utf-8") as f: json.dump(processed_data, f, indent=2)
这个方案的核心是复用PyDantic内置的序列化逻辑,确保特殊类型被正确转换,同时递归处理任意嵌套的结构。
方法2:基于PyDantic内置编码器扩展JSON编码器
可以直接利用pydantic.json.pydantic_encoder来实现自定义JSON编码器,解决混合结构的序列化问题:
import json from pydantic import BaseModel from pydantic.json import pydantic_encoder class PydanticCompatibleEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, BaseModel): # 调用PyDantic内置编码器处理对象 return pydantic_encoder(obj) # 其他类型交给原生编码器处理 return super().default(obj) # 直接使用自定义编码器写入文件 with open("output.json", "w", encoding="utf-8") as f: json.dump(my_dict, f, cls=PydanticCompatibleEncoder, indent=2)
pydantic_encoder已经内置了对datetime、带自定义序列化器对象的处理逻辑,自定义编码器只需判断对象是否为BaseModel实例,再委托给它即可,无需重复实现复杂的序列化逻辑。
内容的提问来源于stack exchange,提问作者bluesummers
相关产品推荐
相关产品推荐

