如何使用Pydantic将映射的键值分别解析为模型属性?
用Pydantic解析键为属性名、值为属性值的映射数据
针对这种单键值对格式的嵌套数据,有三种高效的模型修改方案,直接适配原始数据结构完成解析:
方法一:给Household模型添加前置字段验证器
在Household的pets字段上添加前置验证逻辑,批量将原始单键值对转换为Pet模型可识别的格式:
from typing import Literal, List from pydantic import BaseModel, field_validator class Pet(BaseModel): name: str species: Literal["dog", "cat"] class Household(BaseModel): pets: List[Pet] @field_validator("pets", mode="before") def transform_pet_format(cls, raw_pets): # 遍历每个宠物字典,提取键作为name、值作为species return [ {"name": list(pet.keys())[0], "species": list(pet.values())[0]} for pet in raw_pets ]
使用示例:
data = { "pets": [ {"felix": "cat"}, {"rover": "dog"}, {"snuffles": "dog"}, ] } household = Household(**data) print(household.pets) # 输出:[Pet(name='felix', species='cat'), Pet(name='rover', species='dog'), Pet(name='snuffles', species='dog')]
方法二:让Pet模型直接兼容单键值对输入
通过model_validator让Pet模型本身支持解析单键值对,无需修改Household模型:
from typing import Literal, Any, Dict from pydantic import BaseModel, model_validator class Pet(BaseModel): name: str species: Literal["dog", "cat"] @model_validator(mode="before") def parse_single_key_input(cls, values: Any) -> Dict[str, Any]: # 若输入是单键值对字典,自动转换为标准字段结构 if isinstance(values, dict) and len(values) == 1: name, species = next(iter(values.items())) return {"name": name, "species": species} return values class Household(BaseModel): pets: list[Pet]
这种方式下,直接用Household(**data)即可完成解析,Pet模型会自动处理格式转换。
方法三:用RootModel封装原始宠物结构
借助Pydantic的RootModel定义原始单键值对的结构,再转换为Pet模型,适合需要明确区分原始输入和最终模型的场景:
from typing import Literal, Dict from pydantic import BaseModel, RootModel class PetRaw(RootModel[Dict[str, Literal["dog", "cat"]]]): def to_pet(self) -> "Pet": name, species = next(iter(self.root.items())) return Pet(name=name, species=species) class Pet(BaseModel): name: str species: Literal["dog", "cat"] class Household(BaseModel): pets: list[PetRaw] @field_validator("pets", mode="after") def convert_to_pet_model(cls, raw_pets): return [raw_pet.to_pet() for raw_pet in raw_pets]
内容的提问来源于stack exchange,提问作者SlyFox
相关产品推荐
相关产品推荐

