将JSON文件解析为Pydantic模型

5

我创建了一个Pydantic模型。

但它无法转换并输出错误信息。

请告诉我,出了什么问题。

classDTO

from pydantic import BaseModel,Field
from typing import List,Dict
from datetime import date

class OurBaseModel(BaseModel):
    pass
    #class Config:
        #orm_mode = True

class SessionSubjectDTO(OurBaseModel):
    edu_year: int
    semester_type: str
    
class MarkDTO(OurBaseModel):
    semester_number: int
    subject_name: str
    control_type: str
    mark: str  # or int
    session_subject: SessionSubjectDTO #= Field(None, alias="SessionSubjectDTO")
    
class MarksDTO(OurBaseModel):
    __root__: List[MarkDTO]
    
class AttestationDTO(BaseModel):
    subject_name: str
    value: int
    attestation_start_date: date
    
class AttestationsDTO(OurBaseModel):
    __root__: List[AttestationDTO]
    
class DebtDTO(OurBaseModel):
    semester_number: int
    subject_name: str
    control_type: str
    session_subject: SessionSubjectDTO #= Field(None, alias="SessionSubjectDTO")
    
class DebtsDTO(OurBaseModel):
    __root__: List[DebtDTO]
    
class SkipDTO(OurBaseModel):
    valid: int
    no_valid: int
    attestation_start_date: date
    
class SkipsDTO(OurBaseModel):
    __root__: List[SkipDTO]
    
class StudentDTO(OurBaseModel):
    uid: str
    marks: MarksDTO
    attestations: AttestationsDTO
    debts: DebtsDTO
    skips: SkipsDTO
    
class StudentsDTO(OurBaseModel):
    __root__: List[StudentDTO]

example.json:

[
    {
        "uid": "61c689ac-98a1-11e9-8198-4ccc6a2d123b",
        "marks": [
            {
                "semester_number": 1,
                "subject_name": "454",
                "control_type": "5",
                "mark": "3.",
                "date": "2019-12-27",
                "session_subject": {
                    "id": 4228,
                    "edu_year": 2019,
                    "semester_type": "1"
                }
            }
        ],
        "attestations": [
            {
                "subject_name": "133",
                "value": 2,
                "attestation_start_date": "2019-10-07",
                "attestation_end_date": "2019-10-12"
            }
        ],
        "debts": [
            {
                "semester_number": 4,
                "subject_name": "323",
                "control_type": "12",
                "session_subject": {
                    "id": 22856,
                    "edu_year": 2020,
                    "semester_type": "20"
                }
            }
        ],
        "skips": [
            {
                "valid": null,
                "no_valid": null,
                "attestation_start_date": "2020-03-09",
                "attestation_end_date": "2020-03-14"
            }
        ]
    }
]

main.py:

students = pydantic.parse_file_as(path='192.json', type_=classDTO.StudentsDTO)

错误:

Traceback (most recent call last):
  File "main.py", line 73, in <module>
    students  = pydantic.parse_file_as(path='192.json', type_=classDTO.StudentsDTO)
  File "pydantic\tools.py", line 60, in pydantic.tools.parse_file_as
  File "pydantic\tools.py", line 38, in pydantic.tools.parse_obj_as
  File "pydantic\main.py", line 331, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 424 validation errors for ParsingModel[StudentsDTO]
__root__ -> __root__ -> 0 -> attestations -> __root__ -> 18 -> value
  none is not an allowed value (type=type_error.none.not_allowed)
__root__ -> __root__ -> 0 -> attestations -> __root__ -> 19 -> value
  none is not an allowed value (type=type_error.none.not_allowed)
__root__ -> __root__ -> 0 -> attestations -> __root__ -> 20 -> value
  none is not an allowed value (type=type_error.none.not_allowed)
...
__root__ -> __root__ -> 16 -> skips -> __root__ -> 1 -> no_valid
  none is not an allowed value (type=type_error.none.not_allowed)

我尝试使用自定义根类型来解决此问题:

通过声明字段__root__,可以定义带有自定义根类型的Pydantic模型。

根类型可以是任何由pydantic支持的类型,并且通过__root__字段上的类型提示进行指定。可以通过将根值作为关键字参数__root__传递给模型的__init__方法,或作为parse_obj的第一个唯一参数来传递根值。

1个回答

0

你的 example.json 中的数据似乎只引起了部分错误,而不是全部错误。

原因如下:

例如,在你的 SkipDTO 中,你定义了一个 no_valid: int 字段。

根据这个定义,该字段是 必需的,这就是为什么它不能为 null/None 的原因。

然而,你传入的是:

...
"skips": [
{
        "valid": null,
        "no_valid": null,
        "attestation_start_date": "2020-03-09",
        "attestation_end_date": "2020-03-14"
    }
]
...

如果null 是对于no_valid (和valid) 的有效值,则您需要将模型调整为以下内容:
from typing import List, Dict, Optional

class SkipDTO(OurBaseModel):
    valid: Optional[int]
    no_valid: Optional[int]
    attestation_start_date: date

如果传入了一个null值,那么一个Optional字段将被设置为None
同样的情况可能也适用于AttestationDTO.value和您模型中的其他字段。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接