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

如何基于Pydantic中其他字段的字符串值构建模型?

解决Pydantic基于字符串字段区分模型的问题

错误原因分析

你当前的模型定义逻辑错误:Model类中的model字段被声明为Union[ModelA, ModelB],这意味着Pydantic期望model键对应的值是一个符合ModelA或ModelB结构的嵌套对象,但你的输入JSON是顶层直接包含model和业务字段(比如{"model": "model_a", "some_value": "value_a"}),两者结构不匹配,因此报错"输入需为有效字典或对象而非字符串"。

正确实现方案

核心思路是:让所有子模型共享一个包含鉴别字段(model)的基类,通过固定每个子模型的model字段值,结合Pydantic的discriminator实现自动路由解析。

步骤1:引入依赖并定义基类

from typing import Annotated, Union, Literal
from pydantic import BaseModel, Field, RootModel
class BaseModelWithType(BaseModel):
    model: str

步骤2:定义子模型并固定鉴别字段值

用Literal约束每个子模型的model字段为唯一值,确保Pydantic能准确区分:

class ModelA(BaseModelWithType):
    model: Literal["model_a"] = "model_a"
    some_value: str

class ModelB(BaseModelWithType):
    model: Literal["model_b"] = "model_b"
    another_value: str

步骤3:定义顶层解析模型

有两种常用方式:

方式1:使用RootModel(推荐)

RootModel可以直接接收顶层JSON对象,无需额外嵌套:

class AnyModel(RootModel[Annotated[Union[ModelA, ModelB], Field(discriminator="model")]]):
    pass

方式2:直接用Union验证

无需额外定义顶层模型,直接使用model_validate验证输入:

# 定义类型别名方便复用
ModelUnion = Annotated[Union[ModelA, ModelB], Field(discriminator="model")]

测试验证

# 解析ModelA输入
input_a = {"model": "model_a", "some_value": "value_a"}
result_a = AnyModel.model_validate(input_a)
print(type(result_a.root))  # <class '__main__.ModelA'>
print(result_a.root.some_value)  # value_a

# 解析ModelB输入
input_b = {"model": "model_b", "another_value": "value_b"}
result_b = ModelUnion.model_validate(input_b)
print(type(result_b))  # <class '__main__.ModelB'>
print(result_b.another_value)  # value_b

关键说明

  • discriminator="model"告诉Pydantic通过model字段的值来判断应该使用哪个子模型解析输入。
  • Literal约束确保每个子模型的model字段值唯一,避免解析歧义。
  • 子模型必须继承包含鉴别字段的基类,否则Pydantic无法识别共同的鉴别字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:07:29