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

FastAPI定义Pydantic嵌套列表响应模型返回空的解决方法

问题描述

我尝试为嵌套字典列表结构的数据,在FastAPI中使用Pydantic模型构建response_model,但目前遇到无法解决的问题:只要在路由上添加response_model=配置,API返回的数据就为空;如果移除response_model=配置,相同的API请求可以正常返回包含完整内容的数据。

接口返回的数据结构如下:

[
    {
        'code': 'trabant',
        'description': 'East German Trabant',
        'listings': [
            {
                 id: 1000,
                 cat_no: "Trabi1",
                 descript: "Trabant Interior Mirror",
                 price: Decimal(16.95),
                 veh: 'trabant',
                 sec: 'interior'
             },
             {
                 id: 1001,
                 cat_no: "Trabi2",
                 descript: "Trabant Interior Clock",
                 price: Decimal(56.95),
                 veh: 'trabant',
                 sec: 'interior'
             }
         ]
    },
    {
        'code': 'skoda',
        'description': 'Czech Skoda',
        'listings': [
            {
                  id: 2001,
                  cat_no: "Skoda5",
                  descript: "Front Grille",
                  price: Decimal(36.95),
                  veh: 'skoda',
                  sec: 'bodywork'
             },
             {
                  id: 2002,
                  cat_no: "Skoda6",
                  descript: "Skoda Grille Badge - Front",
                  price: Decimal(16.95),
                  veh: 'skoda',
                  sec: 'bodywork'
             }
        ]
    }
]

提炼后的核心结构如下:

# 根节点为列表
[
    { # 列表可包含40+种任意车辆数据
        'code': str, # 车辆数据库编码
        'description': str, # 车辆文本名称
        'listings': [ # 当前车辆对应的配件目录条目列表
            {
                id: int, # 数据库ID
                cat_no: str, # 客户SKU
                descript: str, # 配件描述
                price: Decimal, # 价格Decimal类型值,不使用浮点数
                veh: str, # 车辆数据库编码
                sec: str # 分区数据库编码
            }
        ]
    }
]

我尝试使用如下Pydantic模型描述该结构:

class ORMBaseModel(BaseModel):
    class Config:
        orm_mode = True

class CatListing(ORMBaseModel):
    id: int
    cat_no: str
    descript: str
    sec: str
    veh: str
    price: Decimal

class VehicleCatListings(ORMBaseModel):
    code: str
    description: str
    listings: List[CatListing]

class ListOfCatListings(ORMBaseModel):
    List[VehicleCatListings]

但当我使用如下路由配置时:

@app.get("/api/cat_no/{ff_no}/listings", response_model=schema.ListOfCatListings)
def getListings(ff_no: str, db: Session = Depends(databases.getDb)):
    listings = crud.catalogue.getListings(db, ff_no) # 数据库请求,返回上述结构的数据

    if listings is None:
        raise HTTPException(status_code=404, detail="FF No catalogue listings not found")
    
    return listings

接口仅返回空对象{},仿佛Pydantic模型以某种方式忽略了传入数据,目前该问题调试难度较大。

注:我并不在销售稀有东欧汽车配件的公司工作,上述内容仅为示例 ;)

问题原因

返回空对象的核心原因是根响应模型定义错误:
接口根返回值是列表类型,但定义的ListOfCatListings是继承自BaseModel的普通对象模型,类体内仅写了List[VehicleCatListings]没有绑定到任何声明字段,Pydantic会将其识别为无字段的空模型,序列化后自然返回空对象{}。

修复方案

不需要额外定义包裹用的ListOfCatListings类,直接在路由的response_model中声明列表类型即可:

  1. 移除无效的ListOfCatListings类定义
  2. 修改路由装饰器的response_model参数为List[schema.VehicleCatListings]

修正后的路由代码:

from typing import List

# CatListing、VehicleCatListings模型保持原有定义即可,无需修改

@app.get("/api/cat_no/{ff_no}/listings", response_model=List[schema.VehicleCatListings])
def getListings(ff_no: str, db: Session = Depends(databases.getDb)):
    listings = crud.catalogue.getListings(db, ff_no)
    if listings is None:
        raise HTTPException(status_code=404, detail="FF No catalogue listings not found")
    return listings

如果需要显式定义根列表类型,Pydantic V2版本可使用RootModel实现,写法如下:

from pydantic import RootModel

class ListOfCatListings(RootModel[List[VehicleCatListings]]):
    pass

该写法同样可以正确识别根节点为列表结构,不会返回空对象。

另外注意示例数据中部分字典条目缺少逗号分隔,实际业务代码中需保证语法正确,避免序列化报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:33:13