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

如何递归将Pydantic模型的所有嵌套字段设为可选?

递归将嵌套Pydantic模型的所有字段设为可选

要实现将嵌套Pydantic模型的所有字段(包括顶层和子模型字段)递归设为可选,可以通过动态生成模型的方式实现,核心思路是递归处理每个字段:如果字段类型是Pydantic模型,则先将该子模型的所有字段设为可选,再将当前字段类型标记为可选;非模型字段直接设为可选类型。

实现代码

from pydantic import BaseModel, create_model
from typing import Optional, TypeVar, Type

# 定义类型变量,限定为BaseModel子类
T = TypeVar('T', bound=BaseModel)

def make_all_fields_optional(model: Type[T]) -> Type[T]:
    fields = {}
    # 遍历原模型的所有字段
    for field_name, field in model.model_fields.items():
        field_type = field.annotation
        # 递归处理嵌套的Pydantic模型字段
        if isinstance(field_type, type) and issubclass(field_type, BaseModel):
            # 先将子模型转为全可选版本
            optional_submodel = make_all_fields_optional(field_type)
            # 字段类型设为Optional[子模型可选版本],保留原默认值(无默认值则设为None)
            fields[field_name] = (Optional[optional_submodel], field.default if field.default is not None else None)
        else:
            # 普通字段直接设为Optional类型,保留原默认值
            fields[field_name] = (Optional[field_type], field.default if field.default is not None else None)
    
    # 动态生成新的全可选模型
    return create_model(
        f"{model.__name__}Optional",
        __base__=model,
        **fields
    )

# 原模型定义
class MyModelE(BaseModel):
    f: float

class MyModelA(BaseModel):
    d: str
    e: MyModelE

class MyModel(BaseModel):
    a: MyModelA
    b: int

# 生成全可选版本的模型
MyModelOptional = make_all_fields_optional(MyModel)

验证效果

可以通过打印模型字段信息确认所有字段已设为可选:

print(MyModelOptional.model_fields)

输出结果中,所有字段(a、b、d、e、f)的类型都会被标记为Optional,且默认值为None(原字段无默认值时)。

注意事项

  • 新生成的模型会继承原模型的配置(如Config类),如果需要自定义配置,可以在create_model中添加__config__参数。
  • 如果原字段已有默认值,该方法会保留原默认值,仅修改字段类型为可选;无默认值的字段会将默认值设为None,符合Optional类型的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:32:05