[Python] How to make Pydantic discriminate a nested object based on a field?

Discussão em 'Python' iniciado por Stack, Janeiro 25, 2025.

  1. Stack

    Stack Membro Participativo

    I have this Pydantic model:

    import typing
    import pydantic

    class TypeAData(pydantic.BaseModel):
    aStr: str

    class TypeBData(pydantic.BaseModel):
    bNumber: int

    class TypeCData(pydantic.BaseModel):
    cBoolean: bool

    class MyData(pydantic.BaseModel):
    type: typing.Literal['A', 'B', 'C']
    name: str
    data: TypeAData | TypeBData | TypeCData


    However, if type is equal to "A" and data contains TypeBData, it'll validate correctly when it shouldn't. This could be an alternative:

    class MyData(pydantic.BaseModel):
    type: typing.Literal['A', 'B', 'C']
    name: str
    data: TypeAData | TypeBData | TypeCData

    @pydantic.validator('data', pre=True, always=True)
    def validate_data(cls, data):
    if isinstance(data, dict):
    data_type = data.get('type')
    if data_type == 'A':
    return TypeAData(**data)
    elif data_type == 'B':
    return TypeBData(**data)
    elif data_type == 'C':
    return TypeCData(**data)

    raise ValueError('Invalid data or type')


    It works; however, is there a better way to do it without repeating the enum keys ('A', 'B' and 'C') and values (TypeAData, TypeBData and TypeCData) twice?

    I've tried using discriminated unions, but since the type field and the discriminated fields are in different levels within the model (the latter is inside a nested object), I could not make further progress on this.

    Continue reading...

Compartilhe esta Página