json 检查某个字段是否存在,取决于另一个字段中的某些条件

inb24sb2  于 2022-12-24  发布在  其他
关注(0)|答案(1)|浏览(137)

我使用Pydantic进行JSON字段类型验证。
我有这个JSON:

json = {
    "id": "string",
    "type": "string enum[initial, calc]",
    "source": "string if type == initial",
    "source_path": "string if type == initial",
    "formula": "string if type == calc"
}

如何使用Pydantic检查带有if-条件的字段?
或者是Pydantic不是正确的工具,我应该使用解析与我自己的函数?
此代码不起作用:
x一个一个一个一个x一个一个二个x

5ssjco0h

5ssjco0h1#

Tag模型的定义似乎不完整,按照描述所需行为的方式,应该定义三个附加字段并使其可选(通过为它们定义合理的默认值),然后才能执行所需的检查。
此外,在check_type方法中,实际上并不赋值或检查任何内容;你只是在那个方法的local命名空间中为formula(或source/source_path)创建类型注解。那些名称和注解不会神奇地延续到类命名空间。此外,验证器必须总是返回一个值,该值将被赋给它指定的字段(在本例中为type)。否则将引发一个适当的异常。
验证器应返回解析值或引发ValueErrorTypeErrorAssertionError
(see docs
最后,我建议您使用root_validator,它们是专门设计来检查整个模型的数据的,这似乎适合您的情况。
以下是我的建议:

from enum import Enum

from pydantic import BaseModel, root_validator

class TypeEnum(Enum):
    initial = "initial"
    calc = "calc"

class Tag(BaseModel):
    id: str
    type: TypeEnum
    formula: str | None = None
    source: str | None = None
    source_path: str | None = None

    @root_validator
    def check_type(cls, values: dict[str, object]) -> dict[str, object]:
        if values["type"] == TypeEnum.calc and values.get("formula") is None:
            raise ValueError("`calc` requires `formula`")
        if values["type"] == TypeEnum.initial:
            if any(values[k] is None for k in {"source", "source_path"}):
                raise ValueError("`initial` requires `source` & `source_path`")
        return values

...

如果使用的是Python <3.10,请使用Optional[str]而不是str | None作为可选字段的注解。
下面是一个快速测试:

...

if __name__ == "__main__":
    from pydantic import ValidationError
    
    print(Tag.parse_obj({
        "id": "string",
        "type": "calc",
        "formula": "string",
    }).json(indent=2), "\n")

    try:
        Tag.parse_obj({
            "id": "string",
            "type": "calc",
            "source": "string",
            "source_path": "string",
        })
    except ValidationError as err:
        print(err.json(), "\n")

    try:
        Tag.parse_obj({
            "id": "string",
            "type": "initial",
            "formula": "string",
            "source": "string",
        })
    except ValidationError as err:
        print(err.json())

输出:
一个一个二个一个一个一个三个一个一个一个一个一个四个一个
根据您的情况,您可能希望为这些条件/可选字段定义一些其他(类型)的默认值。None只是一种典型的方法,当然您可以使用任何您想要的方法。您只需要确保在root_validator方法中对这些默认值执行正确的检查。

相关问题