我使用Pydantic库获得了以下模型结构。我创建了一些类,其中一个类包含另一个类的项列表,所以问题是我不能使用以下类解析json:
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
但后来我像一样使用它
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)
它给了我错误:
ImportsInModel项的1个验证错误->0->
__root__
'NoneType'对象不可下标(type=type_error(
我不知道出了什么问题,因为它实际上是文档的副本。
如果成功,则必须在验证后返回解析结果,即在ImportInModel
中的两个root_validator
的末尾添加return values
。
例如,如果我运行以下代码,就会出现相应的错误:
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
至于ImportsInModel
中的验证器,也许您应该检查代码的逻辑。您的代码想要断言item_1.parentId == item_2.id
。但是,在您的测试用例中,item_1.parentId
永远不会等于item_2.id
,因为您的items
列表中只有一个项目,即item_1 == item_2
。
所以最后的片段是:
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)