You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建含嵌套动态键字典的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())

关键修正点

  1. 调整MyModel的countries字段类型:从Dict[str, Countries]改为Countries,因为Countries模型的__root__已经对应整个国家-城市的字典结构。
  2. Pydantic v1需配置allow_population_by_field_name:确保序列化时自动展开__root__,返回与原字典完全一致的结构;v2版本无需额外配置,默认会展开根类型。

运行修正后的代码,无论是MyModel(**a)还是MyModel.parse_obj(a)都能正常实例化,调用m.dict()会输出与原输入字典完全一致的结构。

内容的提问来源于stack exchange,提问作者Amin Ba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 19:09:53