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

如何在Pydantic嵌套模型中使用子类?

解决方案

要让Pydantic模型支持接受基类的所有子类并在序列化时完整保留子类属性,最可靠的方式是使用**鉴别器(Discriminator)**实现多态类型处理,具体步骤如下:

1. 给基类添加鉴别器字段

在基类Action中定义一个用于区分子类的标识字段(比如type),通过Field(discriminator=True)标记它为鉴别器。每个子类指定唯一的type值,让Pydantic能够识别不同的子类类型。

2. 在父模型中使用带鉴别器的Union类型

在Alert的action字段中,使用Annotated[Union[所有Action子类], Field(discriminator="type")],这样既可以接受所有继承自Action的子类,序列化时也会完整保留子类的所有属性。如果不想手动列举所有子类,可以通过Action.__subclasses__()动态收集已定义的子类(需确保子类在Alert定义前被加载)。

完整代码示例

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

# 基类:定义鉴别器字段
class Action(BaseModel):
    name: str
    type: str = Field(..., discriminator=True)

# 子类1:指定唯一的type标识
class LogAction(Action):
    type: str = "log"
    log_level: str
    timestamp: str

# 子类2:新增的Action子类无需修改Alert即可被支持
class NotifyAction(Action):
    type: str = "notify"
    channel: str
    recipient: str

# 动态收集所有Action子类(可选,替代手动列举)
ActionSubclasses = tuple(Action.__subclasses__())

class Alert(BaseModel):
    id: int
    message: str
    # 使用动态收集的子类集合,或手动写Union[Action, LogAction, NotifyAction]
    action: Annotated[Union[ActionSubclasses], Field(discriminator="type")]

# 测试LogAction实例
alert1 = Alert(
    id=1,
    message="Alert Message",
    action=LogAction(name="Error Log", log_level="ERROR", timestamp="2024-04-20T10:45:00"),
)
print(alert1)
print(alert1.model_dump())

# 测试NotifyAction实例
alert2 = Alert(
    id=2,
    message="Notification Alert",
    action=NotifyAction(name="Send Email", channel="email", recipient="user@example.com"),
)
print(alert2.model_dump())

输出结果

执行后,model_dump()会完整输出子类的所有属性:

Alert(id=1, message='Alert Message', action=LogAction(name='Error Log', type='log', log_level='ERROR', timestamp='2024-04-20T10:45:00'))
{'id': 1, 'message': 'Alert Message', 'action': {'name': 'Error Log', 'type': 'log', 'log_level': 'ERROR', 'timestamp': '2024-04-20T10:45:00'}}
{'id': 2, 'message': 'Notification Alert', 'action': {'name': 'Send Email', 'type': 'notify', 'channel': 'email', 'recipient': 'user@example.com'}}

关键说明

  • 鉴别器字段(这里是type)会被Pydantic用来判断具体的子类类型,序列化和反序列化时都会自动处理。
  • 新增Action子类时,只需指定唯一的type值,无需修改Alert类的定义(使用动态收集子类的方式时)。
  • 如果不需要显式的鉴别器字段,也可以通过model_config中的discriminator参数指定内部标识,但显式定义的方式更直观易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:30:30