[英]How to get json of model pydantic in validator function
Imagine I have Model of pydantic like this:想象一下,我有像这样的 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), }
As you see, I want to get json of model except one field(field4).如您所见,我想获得 model 的 json 除了一个字段(字段4)。 Is there a good solution for handle this inside validator of model???
有没有很好的解决方案来处理 model 的内部验证器?
What the comments failed to address is that Pydantics .json
is an instance method (just like the .dict
method) and thus completely useless inside a validator, which is always a class method called before an instance is even initialized.评论未能解决的是 Pydantics
.json
是一个实例方法(就像.dict
方法一样),因此在验证器中完全没用,验证器始终是在实例初始化之前调用的class方法。
(Note: You did not provide code or explanation about how your ObjectIdField
class works, so I had to make a guess and implement a very simple class to try and simulate the behavior you showed.) (注意:您没有提供有关您的
ObjectIdField
class 如何工作的代码或解释,因此我不得不猜测并实现一个非常简单的 class 来尝试模拟您显示的行为。)
Here is a way to accomplish your validation:这是完成验证的一种方法:
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
The json.dumps
function has a default
parameter, which takes a function json.dumps
function 有一个default
参数,它采用 function
that gets called for objects that can't otherwise be serialized.
对于无法以其他方式序列化的对象,会调用它。
We can use that to construct our own little helper function json_encode
that serializes ObjectIdField
types using the encode_obj_id
function.我们可以使用它来构造我们自己的小助手 function
json_encode
,它使用encode_obj_id
function 序列化ObjectIdField
类型。
Since field4
is not present in the values
dictionary passed to the validator function for that field, we can simply call our json_encode
function on that dictionary and compare it to the field4
value v
.由于
field4
不存在于传递给该字段的验证器 function 的values
字典中,我们可以简单地在该字典上调用我们的json_encode
function 并将其与field4
值v
进行比较。
NOTE : This only works, if field4
is defined last on the model because fields are validated in the order they are defined.注意:这仅适用于字段 4 在
field4
上最后定义的情况,因为字段按照定义的顺序进行验证。 If you had another field after field4
on your model, its value would be missing from the values
dictionary by the time the validator was called.如果您在
field4
上的 field4之后有另一个字段,则在调用验证器时其值将从values
字典中丢失。
Hope this helps.希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.