如何根据已解析字典中的值更改 pydantic 解析的类型?

How can I change the type pydantic parses according to a value in the parsed dictionary?

我希望 pydantic 根据输入值选择用于解析输入的模型。这可能吗?

MVCE

我有一个看起来很像这个的 pydantic 模型:

from typing import List, Literal
from pydantic import BaseModel


class Animal(BaseModel):
    name: str
    type: Literal["mamal", "bird"]


class Bird(Animal):
    max_eggs: int


class Mamal(Animal):
    max_offspring: int


class Config(BaseModel):
    animals: List[Animal]


cfg = Config.parse_obj(
    {
        "animals": [
            {"name": "eagle", "type": "bird", "max_eggs": 3},
            {"name": "Human", "type": "mamal", "max_offspring": 3},
        ]
    }
)

print(cfg.json(indent=4))

给予

{
    "animals": [
        {
            "name": "eagle",
            "type": "bird"
         <-- missing max_offspring, as "Animal" was used instead of Bird
        },
        {
            "name": "Human",
            "type": "mamal"
          <-- missing max_offspring, as "Animal" was used instead of Mamal
        }
    ]
}

我知道我可以在 Animal 中设置 Config.extra="allow",但这不是我想要的。我希望 pydantic 看到带有 'type': 'mamal' 的字典应该使用 Mamal 模型来解析。

这可能吗?

您可以为每个子 class 添加具体的文字来区分它们,并将它们按 Union 从更具体到更不具体的顺序排列。像这样:

class Animal(BaseModel):
    name: str
    type: str


class Bird(Animal):
    type: Literal["bird"]
    max_eggs: int


class Mamal(Animal):
    type: Literal["mamal"]
    max_offspring: int

class Config(BaseModel):
    animals: List[Union[Bird, Mamal, Animal]]  # From more specific to less