如何获取Pydantic BaseModel中含嵌套对象的显式指定实例属性
获取Pydantic BaseModel及其嵌套对象的显式初始化属性
问题场景
我们需要提取Pydantic BaseModel对象及其嵌套对象中仅显式初始化的属性,排除那些使用默认值的属性。现有示例代码如下:
from pydantic import BaseModel class Parameters(BaseModel): id: int sender_id: int = None class Options(BaseModel): notification: bool = False protect: bool = False parameters: Parameters = None opt = Options(protect=True, parameters=Parameters(id=1)) print(opt.model_fields_set) # >>> {'protect', 'parameters'} print(opt.model_dump(include=opt.model_fields_set)) # >>> {'protect': True, 'parameters': {'id': 1, 'sender_id': None}}
当前用model_dump(include=opt.model_fields_set)会保留嵌套对象的默认值属性(比如sender_id: None),但我们期望的结果是:{'protect': True, 'parameters': {'id': 1}}。
你已经实现了一个递归遍历的函数:
def initialized_fields(obj): init_fields = {} for field in obj.model_fields_set: attr = getattr(obj, field) if isinstance(attr, BaseModel): init_fields[field] = initialized_fields(attr) else: init_fields[field] = attr return init_fields
更合适的实现方式
方式1:直接使用Pydantic内置参数(最优解)
Pydantic原生提供了exclude_unset=True参数,专门用于排除所有未显式设置的属性(即使用默认值的属性),包括嵌套对象中的这类属性:
print(opt.model_dump(exclude_unset=True)) # >>> {'protect': True, 'parameters': {'id': 1}}
这个方法无需手动编写递归逻辑,利用框架原生实现,简洁且可靠性更高。
方式2:自定义嵌套include规则(适合精细控制场景)
如果需要更精细地控制序列化字段,可以递归生成嵌套的include规则,再传给model_dump:
def get_nested_fields_set(obj): include = {} for field in obj.model_fields_set: attr = getattr(obj, field) if isinstance(attr, BaseModel): include[field] = get_nested_fields_set(attr) else: include[field] = True return include # 使用示例 print(opt.model_dump(include=get_nested_fields_set(opt))) # >>> {'protect': True, 'parameters': {'id': 1}}
方案对比
- 你自己实现的递归函数是可行的,但需要手动处理类型判断,不如内置方法简洁。
exclude_unset=True是最推荐的方案,它是Pydantic为这类场景设计的原生功能,内部已处理嵌套递归,性能和稳定性更有保障。- 自定义
include规则适合需要额外字段过滤逻辑的场景,但多数情况下exclude_unset=True足够满足需求。
内容的提问来源于stack exchange,提问作者oAsis_88
相关产品推荐
相关产品推荐

