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

如何判断Pydantic模型中Union类型值匹配的具体分支?

判断Pydantic Union类型字段匹配的分支方法

针对你遇到的问题,这里提供三种实用方法来确定Union类型字段匹配的具体分支:

方法一:值匹配+类型特征检查

利用Literal分支的明确字面量,结合其他分支的类型特征直接判断,适合分支逻辑清晰的场景:

from datetime import datetime
from typing import Union, Literal, Tuple, List
from pydantic import BaseModel, UUID4, ValidationError

class ExportDataRequest(BaseModel):
    customers: Union[Literal["all"], List[UUID4], UUID4, List[int], int]
    daterange: Union[Tuple[datetime, datetime], int]

data = {
    "customers": "all",
    'daterange': ("2024-01-01", "2024-03-01")
}

try:
    model = ExportDataRequest(**data)
    
    # 判断customers匹配的分支
    if model.customers == "all":
        print("匹配Literal['all']分支")
    elif isinstance(model.customers, int):
        print("匹配int分支")
    elif isinstance(model.customers, UUID4):
        print("匹配UUID4分支")
    elif isinstance(model.customers, list):
        if all(isinstance(item, UUID4) for item in model.customers):
            print("匹配List[UUID4]分支")
        elif all(isinstance(item, int) for item in model.customers):
            print("匹配List[int]分支")
    
    # 判断daterange匹配的分支
    if isinstance(model.daterange, tuple) and len(model.daterange) == 2 and all(isinstance(d, datetime) for d in model.daterange):
        print("匹配Tuple[datetime, datetime]分支")
    elif isinstance(model.daterange, int):
        print("匹配int分支")

except ValidationError as e:
    print(e.errors())

方法二:解析类型注解+动态验证

通过typing模块解析Union的分支定义,再用Pydantic的TypeAdapter动态验证值是否符合分支,适合复杂Union场景:

from datetime import datetime
from typing import Union, Literal, Tuple, List, get_args, get_origin
from pydantic import BaseModel, UUID4, ValidationError, TypeAdapter

class ExportDataRequest(BaseModel):
    customers: Union[Literal["all"], List[UUID4], UUID4, List[int], int]
    daterange: Union[Tuple[datetime, datetime], int]

data = {
    "customers": "all",
    'daterange': ("2024-01-01", "2024-03-01")
}

try:
    model = ExportDataRequest(**data)
    
    # 处理customers字段
    customers_union = ExportDataRequest.model_fields["customers"].annotation
    if get_origin(customers_union) is Union:
        for branch in get_args(customers_union):
            try:
                TypeAdapter(branch).validate_python(model.customers)
                print(f"customers匹配分支: {branch}")
                break
            except ValidationError:
                continue
    
    # 处理daterange字段
    daterange_union = ExportDataRequest.model_fields["daterange"].annotation
    if get_origin(daterange_union) is Union:
        for branch in get_args(daterange_union):
            try:
                TypeAdapter(branch).validate_python(model.daterange)
                print(f"daterange匹配分支: {branch}")
                break
            except ValidationError:
                continue

except ValidationError as e:
    print(e.errors())

方法三:自定义字段类型封装Literal分支

把Literal["all"]封装成自定义字段类型,让该分支有独立的类型标识,直接通过isinstance判断:

from datetime import datetime
from typing import Union, Tuple, List
from pydantic import BaseModel, UUID4, ValidationError, GetCoreSchemaHandler
from pydantic_core import core_schema

# 自定义类型封装Literal["all"]
class AllLiteral(str):
    @classmethod
    def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        return core_schema.no_info_after_validator_function(
            cls,
            core_schema.literal_schema("all")
        )

class ExportDataRequest(BaseModel):
    customers: Union[AllLiteral, List[UUID4], UUID4, List[int], int]
    daterange: Union[Tuple[datetime, datetime], int]

data = {
    "customers": "all",
    'daterange': ("2024-01-01", "2024-03-01")
}

try:
    model = ExportDataRequest(**data)
    
    print(type(model.customers))  # 输出 <class '__main__.AllLiteral'>
    if isinstance(model.customers, AllLiteral):
        print("匹配原Literal['all']分支")
    # 其他分支判断逻辑同方法一

except ValidationError as e:
    print(e.errors())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:48:22