繁体   English   中英

如何在验证器 function 中获取 model pydantic 的 json

[英]How to get json of model pydantic in validator function

想象一下,我有像这样的 pydantic 的 Model:

 class Input(BaseModel): field1: ObjectIdField =... field2: str =... field3: int =... field4: str =... @validator('field4') def validate_field4(cls, v, values, **kwargs): # print(values) => {'field1': ObjectId('63185d5c721c6ef40eb2462a'), 'field2': 'deleted', 'field3': 1} # I want to check this # if json.dumps(values) == v: # OK # else: # raise Exception return v class Config: json_encoders = { ObjectId: lambda v: str(v), }

如您所见,我想获得 model 的 json 除了一个字段(字段4)。 有没有很好的解决方案来处理 model 的内部验证器?

评论未能解决的是 Pydantics .json是一个实例方法(就像.dict方法一样),因此在验证器中完全没用,验证器始终是在实例初始化之前调用的class方法。

(注意:您没有提供有关您的ObjectIdField class 如何工作的代码或解释,因此我不得不猜测并实现一个非常简单的 class 来尝试模拟您显示的行为。)

这是完成验证的一种方法:

import json
from typing import Any

from pydantic import BaseModel, validator


class ObjectIdField:
    def __init__(self, value: str) -> None:
        self.value = value

    def __repr__(self) -> str:
        return f"ObjectId('{self.value}')"

    def __str__(self) -> str:
        return self.value


def encode_obj_id(obj_id: ObjectIdField) -> str:
    return str(obj_id)


def json_encode(obj: Any) -> str:
    return json.dumps(obj, default=encode_obj_id)


class Input(BaseModel):
    field1: ObjectIdField = ...
    field2: str = ...
    field3: int = ...
    field4: str = ...

    @validator('field4')
    def validate_field4(cls, v: str, values: dict[str, Any]) -> str:
        serialized = json_encode(values)
        assert v == serialized
        return v

    class Config:
        arbitrary_types_allowed = True  # to allow `ObjectIdField`
        json_encoders = {
            ObjectIdField: encode_obj_id,
        }


if __name__ == '__main__':
    data = dict(
        field1=ObjectIdField("abc"),
        field2="foo",
        field3=123,
    )
    data_json = json_encode(data)
    instance = Input(**data, field4=data_json)
    assert data_json == instance.json(exclude={"field4"})

    # instance = Input(**data, field4="invalid")  # this fails validation

json.dumps function 有一个default参数,它采用 function

对于无法以其他方式序列化的对象,会调用它。

我们可以使用它来构造我们自己的小助手 function json_encode ,它使用encode_obj_id function 序列化ObjectIdField类型。

由于field4不存在于传递给该字段的验证器 function 的values字典中,我们可以简单地在该字典上调用我们的json_encode function 并将其与field4v进行比较。

注意:这仅适用于字段 4 在field4上最后定义的情况,因为字段按照定义的顺序进行验证。 如果您在field4上的 field4之后有另一个字段,则在调用验证器时其值将从values字典中丢失。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM