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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:34:51