如何使用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': {}}})
关键注意事项
- 鉴别器层级要清晰:外层联合用顶层
type区分,内层联合用嵌套的container.type区分,每个联合类型都要通过Annotated+Field(discriminator=...)明确标记。 - Literal类型要准确:所有鉴别器字段的
Literal值要和payload里的字符串完全一致,不能有拼写错误。 - 模型继承要正确:如果
ActionsBase是公共基础模型,确保MessageActions和ViewActions正确继承它,避免字段缺失。
如果你的v2.10.4版本还是有问题,可以尝试检查是否有字段拼写错误,或者临时升级到Pydantic v2的最新小版本(比如v2.10.x的后续版本),可能修复了一些鉴别器的小bug。
这样你就不用手动dispatch了,完全可以靠Pydantic的自动鉴别来处理不同类型的Slack交互payload~
备注:内容来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

