我有一个 pydantic 模型,其中包含具有依赖允许值的字段,我希望在 JSON 模式中正确表示这些字段。将其视为类别/子类别关系,例如:
category | subcategory
-----------------------
fruit | apple
fruit | orange
vegetable | cucumber
vegetable | tomato
我的 pydantic 模型看起来像这样:
class Item(pydantic.BaseModel):
category: Literal["fruit", "vegetable"]
subcategory: Literal["apple", "orange", "cucumber", "tomato"]
这是正确的,因为它限制允许的子类别字段不包括
puzzles
或任何其他意外的子类别,但此结构没有正确指定 JSON 模式中类别及其允许的子类别之间的依赖关系。是否可以在 JSON Schema 中指定这种关系?假设这是可能的,用 pydantic 实现这一点的合适方法是什么?
我知道 pydantic 验证器,但这仅在模型实例化时检查传入的数据。在我的用例中,我希望能够允许用户从 UI 中选择有效的类别和子类别,因此 UI 需要通过 JSON 架构了解这些不同字段之间的依赖关系(理想情况下)。
您可以通过创建两个单独的模型来实现此目的,这些模型使用
Literal
s 实现此依赖关系。
让我们创建模型:
from pydantic import BaseModel
from typing import Literal
class Item(BaseModel):
category: str
subcategory: str
class Fruit(Item):
category: Literal['fruit']
subcategory: Literal['apple', 'orange']
class Vegetable(Item):
category: Literal['vegetable']
subcategory: Literal['cucumber', 'tomato']
class Foo(BaseModel):
item: Fruit | Vegetable
这里的关键是我们也有一个类似的模型
Foo
,其中字段类型是所有可能类型的联合。然后 Pydantic 将尝试找到合适的匹配。由于我们使用了 Literal
,因此需要满足依赖关系。
这是一个测试:
Foo(item ={'category': 'fruit', 'subcategory': 'apple'})
# Foo(item=Fruit(category='fruit', subcategory='apple'))
Foo(item={'category': 'fruit', 'subcategory': 'tomato'})
# ValidationError: 2 validation errors for Foo
# item.Fruit.subcategory
# Input should be 'apple' or 'orange' [type=literal_error, input_value='tomato', input_type=str]
# For further information visit https://errors.pydantic.dev/2.6/v/literal_error
# item.Vegetable.category
# Input should be 'vegetable' [type=literal_error, input_value='fruit', input_type=str]
# For further information visit https://errors.pydantic.dev/2.6/v/literal_error