fastapi 如何让 Query 参数支持 List[str] 但允许单值输入

FastAPI中Query参数接收List[str]需用Query(...)声明必填,可自动将单字符串转为单元素列表;若用Query(default=None)则报错,因Pydantic无法将str解析为list。

FastAPI 中 Query 参数

接收 List[str] 但兼容单个字符串输入

FastAPI 默认对 Query 使用类型注解 List[str] 时,要求客户端必须传多个同名参数(如 ?tag=a&tag=b),否则会报 value is not a valid list 错误。但实际中常需要支持单值(?tag=foo)和多值(?tag=foo&tag=bar)两种写法。

关键在于:不能只靠类型注解,得配合 default...(Ellipsis) 显式声明可选性,并让 FastAPI 知道该字段允许“自动展开单值为列表”。

  • Query(default=...) 声明必填(或 Query(default=[]) 声明可选空列表)
  • 类型注解保持 List[str],FastAPI 会自动把单个字符串转成长度为 1 的列表
  • 确保客户端传参方式正确:单值用 ?key=value,多值用 ?key=a&key=b(不是 ?key=a,b
  • 如果想支持逗号分隔的单字符串(如 ?tag=a,b,c),需额外手动解析,FastAPI 不默认处理

为什么直接写 List[str] 有时会报错?

常见错误现象是收到 value is not a valid listtype_error.list,本质是 Pydantic 在校验时发现传入的是 str 而非 list —— 这通常发生在:
  • 你用了 Query(default=None) + List[str],但没设 default=...,导致 FastAPI 无法推断是否允许多值
  • 前端发请求时用了 ?tags=foo,但后端定义成了 tags: Optional[List[str]] = None,此时 Pydantic 尝试把 "foo" 当作 List 解析失败
  • 漏了 from typing import List(Python 3.9+ 可用 list[str],但 FastAPI 0.103+ 才完全支持)

完整可运行示例

from fastapi import FastAPI, Query
from typing import List

app = FastAPI()

@app.get("/search/")
def search(tags: List[str] = Query(..., description="标签列表,支持单值或多值")):
    return {"tags": tags}

调用效果:

  • GET /search/?tags=python{"tags": ["python"]}
  • GET /search/?tags=python&tags=fastapi&tags=web{"tags": ["python", "fastapi", "web"]}
  • GET /search/(无 tags)→ 返回 422,提示缺少必填字段

想支持 ?tags=a,b 形式怎么办?

FastAPI 不原生支持逗号分隔字符串自动转列表。若必须接受这种格式,需手动处理:
  • 把参数类型改为 str,再在函数内用 .split(",")strip()
  • 或者用自定义依赖项封装解析逻辑,避免每个接口重复写
  • 注意空字符串、多余空格、编码问题(如中文逗号)

最易忽略的一点:文档(Swagger UI)里不会自动显示“支持单值”,它只按 List[str] 渲染为多输入框。如果对外暴露 API,得在 description 或额外文档里说明兼容单值写法。