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.
(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.)
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
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.
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.
NOTE: This only works, if field4 is defined last on the model because fields are validated in the order they are defined. 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.
Hope this helps.