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

如何用FastAPI返回包含多种Pydantic模型列表的响应?

FastAPI多类型节点响应去冗余字段解决方案

核心问题原因

FastAPI依赖Pydantic序列化Union类型时,默认会包含所有子模型的字段,未赋值的字段会以null返回,这就是你遇到PersonNode携带SchoolNode的code字段(值为null)的原因。

分步解决方案

1. 正确定义带鉴别器的节点模型

首先要让Pydantic能精准识别节点类型,需要基于带鉴别器的基类定义所有节点模型,每个子类固定label值作为类型标识:

from pydantic import BaseModel, Field
from typing import List, Union

# 基类:定义鉴别器字段label
class BaseNode(BaseModel):
    id: str
    label: str = Field(..., discriminator="label")

# 各子类固定label值,只声明自身专属字段
class SchoolNode(BaseNode):
    label: str = "school"
    code: str

class PersonNode(BaseNode):
    label: str = "person"
    name: str
    surname: str

class PetNode(BaseNode):
    label: str = "pet"
    pet_name: str
    species: str

# 响应模型保持原有结构
class PathResponse(BaseModel):
    nodes: List[Union[SchoolNode, PersonNode, PetNode]]
    edges: List[dict]  # 按实际关系字段定义

2. 序列化时排除未设置字段

在路由返回响应时,调用model_dump(exclude_unset=True),只保留当前节点实例实际赋值的字段,过滤掉其他类型的冗余字段:

from fastapi import FastAPI

app = FastAPI()

@app.get("/shortest-path", response_model=PathResponse)
def get_shortest_path():
    # 模拟业务逻辑生成的节点数据
    person_node = PersonNode(id="p001", name="Alice", surname="Smith")
    school_node = SchoolNode(id="s001", code="SCH-2024")
    pet_node = PetNode(id="t001", pet_name="Milo", species="Cat")
    
    response = PathResponse(
        nodes=[person_node, school_node, pet_node],
        edges=[{"source": "p001", "target": "s001"}]
    )
    
    # 关键:用exclude_unset=True过滤冗余字段
    return response.model_dump(exclude_unset=True)

3. 适配ORM模型场景(如果从数据库取数)

如果节点数据来自ORM模型(比如SQLAlchemy),需要在BaseNode中添加配置,确保从ORM实例转换时只取对应字段:

class BaseNode(BaseModel):
    id: str
    label: str = Field(..., discriminator="label")
    
    class Config:
        from_attributes = True  # 从ORM实例自动映射字段

4. 全局自定义编码器(可选)

如果多个路由都需要处理节点序列化,可以全局配置JSON编码器,避免重复代码:

from fastapi.encoders import jsonable_encoder

def node_encoder(node: BaseNode):
    return node.model_dump(exclude_unset=True)

app = FastAPI(json_encoders={BaseNode: node_encoder})

验证效果

调整后,PersonNode的响应只会包含id、label、name、surname字段,不会出现code这类其他节点的冗余字段,完全适配d3js自定义库的格式要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 07:31:19