FastAPI中Query参数接收List[str]需用Query(...)声明必填,可自动将单字符串转为单元素列表;若用Query(default=None)则报错,因Pydantic无法将str解析为list。
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 不默认处理value is not a valid list 或 type_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,提示缺少必填字段str,再在函数内用 .split(",") 和 strip()
最易忽略的一点:文档(Swagger UI)里不会自动显示“支持单值”,它只按 List[str] 渲染为多输入框。如果对外暴露 API,得在 description 或额外文档里说明兼容单值写法。