在Pydantic BaseModel中创建嵌套DefaultDict遇架构生成错误
问题核心
你定义的嵌套defaultdict[UUID, defaultdict[UUID, dict]]类型可通过pyright类型检查,但运行时Pydantic生成Schema失败,报错无法推断内层defaultdict的键默认工厂;即使尝试给内层类型添加Field注解,问题依然存在。这是因为Pydantic无法正确解析嵌套泛型defaultdict的层级注解,无法识别非内置键类型(UUID)对应的默认逻辑。
解决方案
方案一:为每一层defaultdict显式添加注解
给嵌套结构的每一层defaultdict都用Annotated包裹,明确指定各层的默认工厂:
import pydantic from typing import Annotated from collections import defaultdict from uuid import UUID class Repro(pydantic.BaseModel): value: Annotated[ # 外层defaultdict:键为UUID,值为内层带注解的defaultdict defaultdict[ UUID, Annotated[ # 内层defaultdict:键为UUID,值为dict defaultdict[UUID, dict], # 指定内层defaultdict的默认工厂 pydantic.Field(default_factory=lambda: defaultdict[UUID, dict](dict)) ] ], # 指定外层defaultdict的默认工厂 pydantic.Field(default_factory=lambda: defaultdict[UUID, defaultdict[UUID, dict]]( lambda: defaultdict[UUID, dict](dict) )) ] # 验证运行 instance = Repro() print(instance.value)
方案二:用标准字典类型标注,通过校验器转换为嵌套defaultdict
避开Pydantic对嵌套泛型defaultdict的解析限制,用标准字典类型让Pydantic正常生成Schema,再通过BeforeValidator将输入转换为目标结构:
import pydantic from typing import Annotated from collections import defaultdict from uuid import UUID from pydantic import BeforeValidator def convert_to_nested_defaultdict( value: dict[UUID, dict[UUID, dict]] | None ) -> defaultdict[UUID, defaultdict[UUID, dict]]: outer = defaultdict[UUID, defaultdict[UUID, dict]](lambda: defaultdict(dict)) if value: outer.update(value) return outer class Repro(pydantic.BaseModel): value: Annotated[ dict[UUID, dict[UUID, dict]], BeforeValidator(convert_to_nested_defaultdict), pydantic.Field(default_factory=lambda: defaultdict[UUID, defaultdict[UUID, dict]](lambda: defaultdict(dict))) ] # 验证运行 instance = Repro() print(instance.value) # 测试赋值逻辑 instance.value[UUID('12345678-1234-5678-1234-567812345678')][UUID('87654321-4321-8765-4321-876543210987')] = {"key": "value"} print(instance.value)
原因说明
Pydantic对defaultdict的Schema生成逻辑仅能自动识别内置基础类型(str/int/bool等)作为键的情况,对于UUID这类非内置键类型,必须显式通过Annotated绑定default_factory;嵌套结构下,每一层defaultdict都需要单独注解,否则Pydantic无法正确解析层级关系。
内容的提问来源于stack exchange,提问作者Charles Duffy
相关产品推荐
相关产品推荐

