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

FastAPI如何区分请求中显式传null和未传递的Optional参数?

解决方案

核心思路是利用Pydantic内置的字段传入记录能力,或者自定义哨兵值区分两种场景,以下是两种可落地的方案:

方案1:使用exclude_unset或model_fields_set(官方推荐)

Pydantic模型实例会自动记录所有用户显式传入的字段,不管字段值是否为null:

  • 对于Pydantic V2,可通过实例的model_fields_set属性获取所有已传入字段的集合
  • 对于Pydantic V1,对应的属性为__fields_set__
  • 也可以直接调用model_dump(exclude_unset=True)直接过滤掉所有未传入的字段,仅保留用户主动提交的内容

示例代码修改

from typing import Optional
from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel


class TestEntity(BaseModel):
    first: Optional[str]
    second: Optional[str]
    third: Optional[str]


app = FastAPI()


@app.post("/test")
def test(entity: TestEntity):
    # 仅获取用户主动传入的字段,包含主动设置为null的字段
    update_data = entity.model_dump(exclude_unset=True)
    # 实际业务场景:拿到update_data后,仅更新这些key对应的数据库字段即可
    # 示例返回传入的字段,验证效果
    return update_data


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=5000)

效果验证

提交请求{"first":null}后,接口返回结果为:

{
  "first": null
}

可以准确识别仅first字段为用户主动修改的内容。

方案2:自定义哨兵值区分未传状态

如果需要更明确的类型标注,也可以自定义一个唯一的哨兵值作为字段的默认值,和null做区分:

from typing import Optional, Any
from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel

# 定义唯一的未传标记哨兵
UNSET: Any = object()

class TestEntity(BaseModel):
    first: Optional[str] | type[UNSET] = UNSET
    second: Optional[str] | type[UNSET] = UNSET
    third: Optional[str] | type[UNSET] = UNSET


app = FastAPI()


@app.post("/test")
def test(entity: TestEntity):
    update_data = {}
    for field_name in ["first", "second", "third"]:
        field_value = getattr(entity, field_name)
        if field_value is not UNSET:
            # 只要不是UNSET,不管是None还是正常值都属于用户主动传入
            update_data[field_name] = field_value
    return update_data


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=5000)

该方案和方案1效果完全一致,适合需要在类型层面明确区分未传状态的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 01:27:03