如何用Pydantic实现对象列表与键值字典的双向序列化?
实现方法
要实现列表与键为子对象属性的字典之间的双向序列化/反序列化,可通过自定义Pydantic字段处理器完成,具体步骤如下:
1. 编写双向转换逻辑
先实现两个核心函数,分别处理列表转字典(序列化)、字典转列表(反序列化)的逻辑:
import uuid from typing import List, Dict, Any from pydantic import BaseModel # 序列化:把Recipe列表转为以id为键的字典,同时剔除Recipe对象里的id字段 def serialize_recipes(recipes: List["Recipe"]) -> Dict[str, Dict[str, Any]]: return {str(recipe.id): recipe.model_dump(exclude={"id"}) for recipe in recipes} # 反序列化:把字典转回Recipe列表,字典的键作为Recipe的id def deserialize_recipes(recipes_dict: Dict[str, Dict[str, Any]]) -> List["Recipe"]: return [Recipe(id=uuid.UUID(recipe_id), **recipe_data) for recipe_id, recipe_data in recipes_dict.items()]
2. 自定义Pydantic字段类型
使用Annotated结合Pydantic的序列化/反序列化处理器,创建可复用的字段类型:
from typing import Annotated from pydantic import BeforeValidator, PlainSerializer, WithJsonSchema from pydantic_core import core_schema RecipeDict = Annotated[ List[Recipe], # 反序列化时触发:字典转列表 BeforeValidator(deserialize_recipes), # 序列化时触发:列表转字典 PlainSerializer(serialize_recipes, return_type=dict), # 指定序列化后的JSON Schema格式 WithJsonSchema( { "type": "object", "additionalProperties": { "type": "object", "properties": { "name": {"type": "string"}, "description": {"type": "string"} }, "required": ["name", "description"] } }, mode="serialization", ), # 指定反序列化时的JSON Schema格式 WithJsonSchema( { "type": "array", "items": core_schema.json_schema(Recipe.model_json_schema()) }, mode="deserialization", ), ]
3. 修改模型类
将CountryDetails中的recipes字段替换为自定义的RecipeDict类型:
class Recipe(BaseModel): id: uuid.UUID name: str description: str class CountryDetails(BaseModel): name: str recipes: RecipeDict
4. 测试验证
以下代码可验证序列化和反序列化是否正常工作:
# 测试序列化:生成目标JSON格式 recipe1 = Recipe(id=uuid.UUID("a1acd620-0e87-4cbe-8d15-a4a3aff00cc3"), name="shrimp on the barbie", description="classic prawn on the BBQ") recipe2 = Recipe(id=uuid.UUID("175f2a58-33c4-4886-920f-cb073101f104"), name="vegemite toast", description="toast + vegemite; nice") country = CountryDetails(name="australia", recipes=[recipe1, recipe2]) print(country.model_dump_json(indent=2)) # 测试反序列化:从目标JSON转回对象 json_str = ''' { "name": "australia", "recipes": { "a1acd620-0e87-4cbe-8d15-a4a3aff00cc3": { "name": "shrimp on the barbie", "description": "classic prawn on the BBQ" }, "175f2a58-33c4-4886-920f-cb073101f104": { "name": "vegemite toast", "description": "toast + vegemite; nice" } } } ''' deserialized_country = CountryDetails.model_validate_json(json_str) print(deserialized_country.recipes)
关键说明
- 序列化时通过
PlainSerializer自动调用转换函数,把列表转为指定格式的字典,同时剔除重复的id字段; - 反序列化时通过
BeforeValidator触发反向转换,从字典重构出对象列表; - 配置
WithJsonSchema确保生成的JSON Schema符合预期,适配前后端交互的格式要求。
内容的提问来源于stack exchange,提问作者Ramon
相关产品推荐
相关产品推荐

