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

如何为FastAPI嵌套模型单独设置exclude_unset导出行为?

问题描述

假设我有如下基于Pydantic的FastAPI模型:

class Filter(BaseModel, extra=Extra.forbid):
    expression: str | None
    kind: str | None
    ...

class Configuration(BaseModel):
    filter: Filter | None = {}
    ....

默认情况下,当未给filter传任何值时,模型导出的结果是这样的:

{
   "filter": {
       "expression": null,
       "kind": null,
       ...
   },
   ...
}

但我想要的导出结果是:

{
   "filter": {},
   ...
}

现在需要实现:让这个嵌套的Filter模型在导出时始终应用exclude_unset行为,且在复杂模型中仅针对部分嵌套模型排除未设置字段,其他模型保留原有字段。已知全局的exclude_unset和response_model_exclude_unset会影响整个模型,因此需要单独控制单个嵌套模型的序列化行为。


解决方案

方法一:给嵌套模型强制添加序列化规则

直接修改Filter模型,让它在序列化时默认启用exclude_unset=True,这样不管父模型怎么设置,这个嵌套模型自身都会排除未设置的字段。

修改后的Filter模型代码:

from pydantic import BaseModel, Extra

class Filter(BaseModel, extra=Extra.forbid):
    expression: str | None
    kind: str | None
    ...

    def dict(self, **kwargs):
        # 强制转字典时排除未设置字段
        kwargs.setdefault('exclude_unset', True)
        return super().dict(**kwargs)

    def json(self, **kwargs):
        # 强制转JSON时应用同样规则
        kwargs.setdefault('exclude_unset', True)
        return super().json(**kwargs)

只要是Filter的实例,序列化后都会自动去掉未设置的字段,空实例就会输出{}。

方法二:在父模型中单独处理目标字段

如果不想改动Filter模型的全局行为,可以在父模型Configuration里给filter字段添加序列化器,单独对它应用exclude_unset规则。

示例代码:

from pydantic import BaseModel, Extra, field_serializer

class Filter(BaseModel, extra=Extra.forbid):
    expression: str | None
    kind: str | None
    ...

class Configuration(BaseModel):
    filter: Filter | None = {}
    ....

    @field_serializer('filter')
    def serialize_filter(self, value: Filter | None) -> dict | None:
        if not value:
            return {}
        # 仅对当前filter字段应用exclude_unset=True
        return value.dict(exclude_unset=True)

这种方式只会在Configuration模型里生效,其他地方使用Filter模型时不受影响。

方法三:FastAPI接口中手动构造响应

如果只是在某个接口的响应里需要这个效果,可以在返回数据时手动处理filter字段的序列化:

from fastapi import FastAPI

app = FastAPI()

@app.get("/config", response_model=Configuration)
def get_config():
    config = Configuration()
    # 先把整个模型转成字典,再替换filter字段的序列化结果
    resp_data = config.dict()
    resp_data['filter'] = config.filter.dict(exclude_unset=True) if config.filter else {}
    return resp_data

这种方法适合临时的局部场景,无需修改模型定义。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:17:09