如何递归将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
相关产品推荐
相关产品推荐

