WheatField
WheatField

FastAPI 返回值中排除 None 值

December 19, 2024456 words, 3 min read
Authors

经常用 FastAPI 开发 API 的同学都知道,FastAPI 与 Pydantic 天生一对,在接收 JSON 请求时,FastAPI 可以自动将 JSON 转换为 Pydantic 模型,同样在接口返回时,FastAPI 也能自动将 Pydantic 模型转换为 JSON 格式。

这种羁绊,像极了爱情。

Pydantic 与 FastAPI

但有时候,我们希望在返回数据时,希望过滤掉一些字段。比如,在返回一个 API 响应时,如果 error 字段为空,则不需要返回。反之,如果 error 字段不为空,data 可能就为空,既然已经报错,data 也就没必要返回了。

class ResponseType(BaseModel):
    code: Optional[int] = None
    message: Optional[str] = None
    data: Optional[dict] = None
    error: Optional[str] = None

那如何实现呢?常规操作有两种方法,这里先说第二种:

二、 使用 Pydantic 的 exclude_none 选项

既然模型(BaseModel)中含有 None 值,那我们就不能直接返回这个模型,不然 FastAPI 会将其转换为 JSON 响应。 因此,在返回前可以先通过 Pydantic 的序列化方法 model_dump 方法 + exclude_none=True 选项,来排除 None 值,如此可以得到一个字典,然后 FastAPI 再将其转换为 JSON 响应。

@app.get("/response")
async def get_response():
    response = ResponseType(code=1, message="success", data={"name": "John"})
    return response.model_dump(exclude_none=True)

一、使用 FastAPI 的 response_model_exclude_none=True

参考 GitHub 上的讨论 的方法,通过 response_model_exclude_none=True 选项,FastAPI 会自动将 ResponseType 中的 None 值排除,然后返回。

@app.get("/response", response_model=ResponseType, response_model_exclude_none=True)
async def get_response():
    response = ResponseType(code=1, message="success", data={"name": "John"})
    return response

注:这里 response_model 是必须的。

当然,这两种方法是比较直观的方法,如果这两种方式不够有逼格,也可以参考之前关于 《Pydantic 序列化的一些小技巧》 中有提到 model_serialize 方法,可以筛选出需要返回的字段,但这样未免有点小题大做了,杀鸡用牛刀了。

Comments