I have the following structure of the models using Pydantic library. I created some of the classes, and one of them contains list of items of another, so the problem is that I can't parse json using this classes:
class FileTypeEnum(str, Enum):
file = 'FILE'
folder = 'FOLDER'
class ImportInModel(BaseModel):
id: constr(min_length=1)
url: constr(max_length=255) = None
parentId: str | None = None
size: PositiveInt | None = None
type: FileTypeEnum
@root_validator
def check_url(cls, values: dict):
file_type = values['type']
file_url = values['url']
if file_type == FileTypeEnum.folder and file_url is not None:
raise ValueError(
f'{file_type}\'s type file has {file_url} file url!'
)
@root_validator
def check_size(cls, values: dict):
file_type = values['type']
file_size = values['size']
if file_type == FileTypeEnum.file and file_size is None:
raise ValueError(
f'{file_type}\'s type file has {file_size} file size!'
)
class ImportsInModel(BaseModel):
items: list[ImportInModel]
updateDate: datetime
class Config:
json_encoders = {
datetime: isoformat
}
json_loads = ujson.loads
@validator('items')
def check_parent(cls, v):
for item_1 in v:
for item_2 in v:
print(item_1.type, item_1.parentId, item_2.id, item_2.type)
assert item_1.type == FileTypeEnum.file \
and item_1.parentId == item_2.id \
and item_2.type == FileTypeEnum.folder
But then I use it like
try:
json_raw = '''{
"items": [
{
"id": "элемент_1_4",
"url": "/file/url1",
"parentId": "элемент_1_1",
"size": 234,
"type": "FILE"
}
],
"updateDate": "2022-05-28T21:12:01.000Z"
}
'''
ImportsInModel.parse_raw(json_raw)
# print(json_)
except ValidationError as e:
print(e)
It gives me error:
1 validation error for ImportsInModel items -> 0 ->
__root__
'NoneType' object is not subscriptable (type=type_error)
And I have no idea what's wrong, because it literally copy of the documentation.
You have to return parsed result after validation if success, i.e., you should add return values in the end of the two root_validator in ImportInModel.
For instance, if I run below code, a corresponding error will throw up:
if __name__ == '__main__':
try:
x_raw = '''
{
"id": "элемент_1_4",
"url": "/file/url1",
"parentId": "элемент_1_1",
"size": 234,
"type": "FILE"
}
'''
y = ImportInModel.parse_raw(x_raw)
except ValidationError as e:
print(e)
Traceback (most recent call last):
File "pydantic/main.py", line 344, in pydantic.main.BaseModel.__init__
TypeError: __dict__ must be set to a dictionary, not a 'NoneType'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/will/PycharmProjects/pythonProject2/pydantic_1.py", line 90, in <module>
y = ImportInModel.parse_raw(x_raw)
File "pydantic/main.py", line 549, in pydantic.main.BaseModel.parse_raw
File "pydantic/main.py", line 526, in pydantic.main.BaseModel.parse_obj
File "pydantic/main.py", line 346, in pydantic.main.BaseModel.__init__
TypeError: Model values must be a dict; you may not have returned a dictionary from a root validator
As for the validator in ImportsInModel, maybe you should check your logic of the code. You codes want to assert item_1.parentId == item_2.id. However, in your testcase, item_1.parentId will never equal to item_2.id since you only have one item in your items list, which means item_1 == item_2.
So the final snippet is:
from datetime import datetime
from enum import Enum
import ujson
from pydantic.json import isoformat
from pydantic import BaseModel, constr, PositiveInt, root_validator, validator, ValidationError
class FileTypeEnum(Enum):
file = 'FILE'
folder = 'FOLDER'
class ImportInModel(BaseModel):
id: constr(min_length=1)
url: constr(max_length=255) = None
parentId: str | None = None
size: PositiveInt | None = None
type: FileTypeEnum
@root_validator
def check_url(cls, values: dict):
file_type = values['type']
file_url = values['url']
if file_type == FileTypeEnum.folder and file_url is not None:
raise ValueError(
f'{file_type}\'s type file has {file_url} file url!'
)
return values
@root_validator
def check_size(cls, values: dict):
file_type = values['type']
file_size = values['size']
if file_type == FileTypeEnum.file and file_size is None:
raise ValueError(
f'{file_type}\'s type file has {file_size} file size!'
)
return values
class ImportsInModel(BaseModel):
items: list[ImportInModel]
updateDate: datetime
class Config:
json_encoders = {
datetime: isoformat
}
json_loads = ujson.loads
@validator('items')
def check_parent(cls, v):
for item_1 in v:
for item_2 in v:
print(item_1.type, item_1.parentId, item_2.id, item_2.type)
assert item_1.type == FileTypeEnum.file \
and item_1.parentId == item_2.id \
and item_2.type == FileTypeEnum.folder
if __name__ == '__main__':
try:
json_raw = '''{
"items": [
{
"id": "элемент_1_4",
"url": "/file/url1",
"parentId": "элемент_1_1",
"size": 234,
"type": "FILE"
}
],
"updateDate": "2022-05-28T21:12:01.000Z"
}
'''
x_raw = '''
{
"id": "элемент_1_4",
"url": "/file/url1",
"parentId": "элемент_1_1",
"size": 234,
"type": "FILE"
}
'''
y = ImportInModel.parse_raw(x_raw)
z = ImportsInModel.parse_raw(json_raw)
print(y, z)
except ValidationError as e:
print(e)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With