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

如何基于父模型protocol字段实现Pydantic Union鉴别器?

Pydantic实现跨字段关联的模型反序列化

完全可以实现这种需求,核心是用自定义模型验证器,在反序列化时根据protocol字段的值,动态把protocol_params解析成对应的模型。下面是针对多协议场景的具体实现:

1. 定义各协议参数模型

先把所有协议对应的参数模型写好,后续新增协议直接扩展即可:

from pydantic import BaseModel, ValidationError, model_validator
from typing import Union, Dict, Any

class ProtocolOneParam(BaseModel):
    param_a: str
    param_b: int

class ProtocolTwoParam(BaseModel):
    param_c: float
    param_d: bool

# 示例新增协议参数模型
class ProtocolThreeParam(BaseModel):
    param_e: list[str]

2. 建立协议与模型的映射表

用字典绑定协议字符串和对应参数模型,方便后续快速匹配:

PROTOCOL_MODEL_MAP = {
    "protocol1": ProtocolOneParam,
    "protocol2": ProtocolTwoParam,
    "protocol3": ProtocolThreeParam,
    # 继续添加其他协议的映射关系...
}

3. 在Foo模型中添加自定义验证逻辑

使用Pydantic 2.x的@model_validator(mode='before')(若为1.x版本则替换为@root_validator(pre=True)),在模型解析前完成动态匹配:

class Foo(BaseModel):
    protocol: str
    protocol_params: Union[ProtocolOneParam, ProtocolTwoParam, ProtocolThreeParam]

    @model_validator(mode='before')
    def resolve_protocol_params(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        protocol = values.get("protocol")
        params = values.get("protocol_params")
        
        if protocol and params:
            target_model = PROTOCOL_MODEL_MAP.get(protocol)
            if not target_model:
                raise ValueError(f"不支持的协议类型: {protocol}")
            # 手动将参数解析为目标模型
            values["protocol_params"] = target_model.model_validate(params)
        
        return values

4. 测试验证

用以下代码验证功能是否正常:

# 测试protocol1场景
foo1 = Foo.model_validate({
    "protocol": "protocol1",
    "protocol_params": {"param_a": "test", "param_b": 123}
})
print(type(foo1.protocol_params))  # 输出 <class '__main__.ProtocolOneParam'>

# 测试protocol2场景
foo2 = Foo.model_validate({
    "protocol": "protocol2",
    "protocol_params": {"param_c": 3.14, "param_d": True}
})
print(type(foo2.protocol_params))  # 输出 <class '__main__.ProtocolTwoParam'>

# 测试不支持的协议
try:
    Foo.model_validate({
        "protocol": "unknown",
        "protocol_params": {}
    })
except ValidationError as e:
    print(e)  # 抛出"不支持的协议类型: unknown"的错误

注意事项

  • 若使用Pydantic 1.x,仅需将@model_validator(mode='before')替换为@root_validator(pre=True),核心逻辑保持不变。
  • 后续新增协议时,只需添加对应的参数模型和映射关系,无需修改验证器代码,扩展性极强。

内容的提问来源于stack exchange,提问作者M.Armoun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:53:29