如何创建含嵌套动态键字典的Pydantic模型并保留原结构
问题分析与解决方案
你的代码核心问题在于**MyModel中countries字段的类型定义错误**:你将其设为Dict[str, Countries],但Countries本身已经是封装了Dict[str, Cities]的根类型模型,这会导致解析时类型不匹配。
修正后的代码
Pydantic v2版本
from typing import Dict from pydantic import BaseModel class Address(BaseModel): address: str class Cities(BaseModel): __root__: Dict[str, Address] def __iter__(self): return iter(self.__root__) def __getitem__(self, item): return self.__root__[item] class Countries(BaseModel): __root__: Dict[str, Cities] def __iter__(self): return iter(self.__root__) def __getitem__(self, item): return self.__root__[item] class MyModel(BaseModel): name: str countries: Countries # 修正为Countries类型,而非Dict[str, Countries] # 测试数据 a = { "name": "dummy", "countries": { "us": { "newyork": {"address": "dummy address"}, "boston": {"address": "dummy address"} }, "canada": {"toronto": {"address": "dummy address"}} } } # 实例化与验证 m = MyModel.parse_obj(a) # 或 m = MyModel(**a) print(m.dict())
Pydantic v1版本(需添加Config配置)
from typing import Dict from pydantic import BaseModel class Address(BaseModel): address: str class Cities(BaseModel): __root__: Dict[str, Address] def __iter__(self): return iter(self.__root__) def __getitem__(self, item): return self.__root__[item] class Config: allow_population_by_field_name = True class Countries(BaseModel): __root__: Dict[str, Cities] def __iter__(self): return iter(self.__root__) def __getitem__(self, item): return self.__root__[item] class Config: allow_population_by_field_name = True class MyModel(BaseModel): name: str countries: Countries # 测试数据 a = { "name": "dummy", "countries": { "us": { "newyork": {"address": "dummy address"}, "boston": {"address": "dummy address"} }, "canada": {"toronto": {"address": "dummy address"}} } } m = MyModel.parse_obj(a) print(m.dict())
关键修正点
- 调整
MyModel的countries字段类型:从Dict[str, Countries]改为Countries,因为Countries模型的__root__已经对应整个国家-城市的字典结构。 - Pydantic v1需配置
allow_population_by_field_name:确保序列化时自动展开__root__,返回与原字典完全一致的结构;v2版本无需额外配置,默认会展开根类型。
运行修正后的代码,无论是MyModel(**a)还是MyModel.parse_obj(a)都能正常实例化,调用m.dict()会输出与原输入字典完全一致的结构。
内容的提问来源于stack exchange,提问作者Amin Ba
相关产品推荐
相关产品推荐

