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

如何使用Pydantic v2处理多层嵌套的鉴别器(Discriminator)?

如何使用Pydantic v2处理多层嵌套的鉴别器(Discriminator)?

我来帮你搞定这个多层嵌套鉴别器的问题!在Pydantic v2里其实完全支持这种先按外层type区分、再按嵌套字段container.type细分的逻辑,你之前的写法只差一点点调整就能正常工作。

首先,咱们先理清楚你的需求:你需要先通过顶层的type字段区分view_submission和block_actions类型的请求,然后对block_actions类型,再通过container.type区分是消息容器还是视图容器的交互。

修正后的代码实现

先把模型定义和鉴别器设置调整成下面这样:

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

# 基础 Actions 模型(如果有公共字段的话)
class ActionsBase(BaseModel):
    user_id: str  # 示例公共字段,根据你的实际需求调整

# 容器模型
class MessageContainer(BaseModel):
    type: Literal["message"]
    channel_id: str  # 示例字段,替换成你的实际字段

class ViewContainer(BaseModel):
    type: Literal["view"]
    view_id: str  # 示例字段,替换成你的实际字段

# 具体的交互模型
class MessageActions(ActionsBase):
    type: Literal["block_actions"]
    container: MessageContainer

class ViewActions(ActionsBase):
    type: Literal["block_actions"]
    container: ViewContainer

class ViewSubmission(BaseModel):
    type: Literal["view_submission"]
    view: dict  # 示例字段,替换成你的实际视图字段

# 第一步:定义内层联合,用 container.type 作为鉴别器
BlockActions = Annotated[
    Union[MessageActions, ViewActions],
    Field(discriminator="container.type")
]

# 第二步:定义外层联合,用顶层 type 作为鉴别器
SlackInteraction = Annotated[
    Union[ViewSubmission, BlockActions],
    Field(discriminator="type")
]

测试验证

现在你可以用不同的payload测试解析效果:

# 测试消息容器的 block_actions
message_payload = {
    "type": "block_actions",
    "user_id": "U12345",
    "container": {
        "type": "message",
        "channel_id": "C67890"
    }
}

# 测试视图容器的 block_actions
view_actions_payload = {
    "type": "block_actions",
    "user_id": "U12345",
    "container": {
        "type": "view",
        "view_id": "V09876"
    }
}

# 测试 view_submission
view_submission_payload = {
    "type": "view_submission",
    "view": {"id": "V09876", "state": {"values": {}}}
}

# 创建适配器并验证
adapter = TypeAdapter(SlackInteraction)

print(adapter.validate_python(message_payload))
# 输出:MessageActions(type='block_actions', user_id='U12345', container=MessageContainer(type='message', channel_id='C67890'))

print(adapter.validate_python(view_actions_payload))
# 输出:ViewActions(type='block_actions', user_id='U12345', container=ViewContainer(type='view', view_id='V09876'))

print(adapter.validate_python(view_submission_payload))
# 输出:ViewSubmission(type='view_submission', view={'id': 'V09876', 'state': {'values': {}}})

关键注意事项

  1. 鉴别器层级要清晰:外层联合用顶层type区分,内层联合用嵌套的container.type区分,每个联合类型都要通过Annotated+Field(discriminator=...)明确标记。
  2. Literal类型要准确:所有鉴别器字段的Literal值要和payload里的字符串完全一致,不能有拼写错误。
  3. 模型继承要正确:如果ActionsBase是公共基础模型,确保MessageActions和ViewActions正确继承它,避免字段缺失。

如果你的v2.10.4版本还是有问题,可以尝试检查是否有字段拼写错误,或者临时升级到Pydantic v2的最新小版本(比如v2.10.x的后续版本),可能修复了一些鉴别器的小bug。

这样你就不用手动dispatch了,完全可以靠Pydantic的自动鉴别来处理不同类型的Slack交互payload~

备注:内容来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:18:06