Skip to content

15. FastAPI 响应类型_列表格式 ​

列表响应描述一组同类资源 ​

JSON 顶层可以直接是数组,如 [{"id":1},{"id":2}]。list[ItemOut] 表示“列表中的每一项都符合 ItemOut”,而不是只检查列表外壳。

python
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class ItemOut(BaseModel):
    id: int
    name: str
    tags: list[str] = []

@app.get("/items", response_model=list[ItemOut])
def list_items():
    return [
        {"id": 1, "name": "键盘", "tags": ["办公"], "cost": 80},
        {"id": 2, "name": "鼠标", "tags": [], "cost": 30},
    ]

@app.get("/empty", response_model=list[ItemOut])
def empty_items():
    return []

保存为 main.py,运行 uv run uvicorn main:app --reload。/items 返回两个对象,内部成本 cost 被过滤;/empty 返回 []。列表为空通常是成功结果,不必使用 404。

本例列表默认值由 Pydantic 处理;在自己的普通 Python 函数或数据类中不要据此照搬可变默认参数,工程里也可以统一使用 Field(default_factory=list)。

裸数组还是封装对象 ​

格式优点适合
[{...}]简单、客户端直接遍历小型固定集合
{"items":[...],"total":100}可带总量、页码、游标分页与长期演进

接口一旦对外使用,从数组改成对象会影响客户端,应提前决定协议。第 17 篇会实现可复用分页模型。

从数据库返回时的注意点 ​

不要直接拿 SQLAlchemy 的 Row 当普通实体。查询实体常用 session.scalars(select(Item)).all();选择多列时常用 .mappings() 或明确转字典。Pydantic 读取 ORM 属性需要 ConfigDict(from_attributes=True)。

有关联关系时,输出嵌套模型可能触发额外数据库查询。应先选择加载策略,避免每个列表项都再查一次数据库。千万条记录不能因为声明了列表模型就一次性全部返回,应限制每次查询数量。

类型与输出契约 ​

列表中的任何一个元素缺少必填字段,都可能让整个响应校验失败。这是服务端问题,应通过测试提前发现。直接返回生成器也不等于网络流式传输;逐块输出要使用 StreamingResponse 等流式响应。

练习:增加第三个商品,故意遗漏 name,观察服务端校验失败;修复后再测试空列表。为一个“城市字典”接口选择裸数组或封装对象,并说明理由。