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

如何使用Pydantic与FastAPI正确验证递归结构的Filter模型数据?

解决Pydantic递归Union模型的类型识别问题

你的问题出在两个关键点上:一是type没有被定义为Pydantic的字段,二是没有利用Pydantic的鉴别器功能来明确区分不同的过滤器模型。下面是具体的解决方法:

1. 修正模型定义(核心修改)

首先,把SimpleFilter和CompoundFilter里的type从类属性改为Pydantic字段,然后给subfilters字段添加鉴别器,让Pydantic能根据type字段的值自动选择对应的模型验证:

from enum import Enum
from typing import Any, List, Union
from pydantic import BaseModel, Field

class FilterType(str, Enum):
    SIMPLE = "simple"
    COMPOUND = "compound"

class Operator(str, Enum):
    AND = "and"
    OR = "or"

class FilterAction(str, Enum):
    INCLUDE = "include"
    EXCLUDE = "exclude"

class Comparator(str, Enum):
    EQUAL = "=="
    NOT_EQUAL = "!="
    # 注意:你的测试数据用了">=",需要补充这个枚举值,否则会验证失败
    GREATER_THAN_OR_EQUAL = ">="

class SimpleFilter(BaseModel):
    # 将type改为Pydantic字段,设置默认值
    type: FilterType = FilterType.SIMPLE
    action: FilterAction = FilterAction.EXCLUDE
    comparator: Comparator
    criterion: Any

class CompoundFilter(BaseModel):
    # 同样将type改为Pydantic字段
    type: FilterType = FilterType.COMPOUND
    operator: Operator = Operator.AND
    # 为subfilters添加discriminator,指定根据type字段区分模型
    subfilters: List[Union[SimpleFilter, "CompoundFilter"]] = Field(
        default_factory=list,
        discriminator="type"
    )

CompoundFilter.update_forward_refs()

2. 关键修改说明

  • 将type改为Pydantic字段:原来的type = FilterType.SIMPLE是类属性,Pydantic不会把它作为模型的一部分进行验证和解析。改成type: FilterType = FilterType.SIMPLE后,这个字段会被纳入验证逻辑,传入的JSON中的type值会被正确读取。
  • 添加鉴别器discriminator="type":这个参数告诉Pydantic,对于Union[SimpleFilter, CompoundFilter]类型的元素,要根据它们的type字段值来选择对应的模型。当type为"simple"时用SimpleFilter验证,为"compound"时用CompoundFilter验证,彻底避免了顺序匹配导致的错误。

3. 测试修正后的代码

注意你的测试数据里有两个小问题:SimpleFilter要求必填criterion字段,且comparator: ">="不在原来的枚举里,修正后的数据如下:

data = {
    "type": "compound",
    "operator": "and",
    "subfilters": [
        {
            "type": "simple",
            "action": "exclude",
            "comparator": ">=",
            "criterion": 100  # 补充必填的criterion字段
        }
    ]
}

# 实例化验证
filter_obj = CompoundFilter(**data)
print(filter_obj.subfilters[0])
# 输出:type=<FilterType.SIMPLE: 'simple'> action=<FilterAction.EXCLUDE: 'exclude'> comparator=<Comparator.GREATER_THAN_OR_EQUAL: '>='> criterion=100

现在subfilters里的元素会被正确识别为SimpleFilter类型,而不是错误匹配到CompoundFilter。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:12:36