使用Pydantic验证JSON遇字段验证器错误,需在subject类获取grade
问题解决步骤
1. 修复 ConfigError: Validators defined with incorrect fields: validate_grade 错误
这个错误的核心原因是你定义的Grade类仅添加了字段验证器,但未声明对应的grade字段。Pydantic要求验证器必须绑定到类中已定义的字段上,同时验证器必须返回处理后的值(否则会将字段值置为None)。
修正后的Grade类(如果需要单独定义):
from pydantic import BaseModel, validator class Grade(BaseModel): # 必须先声明对应的字段,验证器才能绑定 grade: str @validator("grade") def validate_grade(cls, val): if val is None: raise ValueError("grade is null") # 验证器必须返回值,否则字段会被设为None return val
2. 修正JSON语法错误
你的JSON数据存在两处语法问题:
"grade": "A"末尾缺少逗号subject数组内的对象多了一个闭合大括号
修正后的JSON:
{ "grade": "A", "subject": [ { "physics": "PHY", "chemistry": "CHE", "classTime": { "date": "2024-03-25", "time": null }, "labTime": null } ] }
3. 在Subject类中获取grade字段的解决方案
由于Subject是嵌套在顶层数据中的子模型,默认无法直接访问父级的grade字段。可以通过顶层模型的全局验证器实现,将grade和subject结合验证:
完整代码示例
from pydantic import BaseModel, validator, root_validator from typing import List, Optional class Subject(BaseModel): physics: str chemistry: str classTime: dict labTime: Optional[dict] = None @validator("classTime", pre=True, always=True) def validate_classTime(cls, value): date_str = value.get('date', '') time_str = value.get('time', '') # 添加classTime的验证逻辑,比如检查日期非空 if not date_str: raise ValueError("classTime date cannot be empty") return value # 定义顶层模型,包含整个JSON的结构 class Report(BaseModel): grade: str subject: List[Subject] @validator("grade") def validate_grade(cls, val): if val is None: raise ValueError("grade is null") return val @root_validator(skip_on_failure=False) def validate_subject_with_grade(cls, values): # 从values中同时获取grade和subject数据 grade = values.get("grade") subjects = values.get("subject") if subjects and grade: # 这里可以根据grade值对每个subject做自定义验证 # 示例:如果grade为"A",检查labTime是否为空(可根据需求调整逻辑) for subj in subjects: if grade == "A" and subj.labTime is not None: raise ValueError(f"Grade A should have no lab time for subject {subj.physics}") return values # 测试解析JSON test_json = { "grade": "A", "subject": [ { "physics": "PHY", "chemistry": "CHE", "classTime": { "date": "2024-03-25", "time": null }, "labTime": null } ] } report = Report(**test_json) print(report.dict())
说明
- 顶层模型
Report承载了整个JSON的结构,通过root_validator可以同时获取grade和subject数据,实现跨字段的关联验证。 - 如果使用Pydantic v2,可以将
root_validator替换为model_validator(mode='after'),用法逻辑一致。
内容的提问来源于stack exchange,提问作者Ullan
相关产品推荐
相关产品推荐

