You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python基于POJO类实现JSON模式匹配(类Scala)及报错排查

问题原因

你遇到的AttributeError本质是嵌套的字典没有被转换成对应的类实例:

  • 只有Student类使用了@dataclass装饰器,而SubjectDetails、GradeDetails只是普通的注解类,没有实例化逻辑。
  • 当用Student(**data_dict)初始化时,data_dict['subjects']是一个字典,不会自动转换成SubjectDetails对象,所以student_data.subjects实际上是dict类型,自然没有subject_name属性。
最佳实现方案

方案1:基于dataclass手动处理嵌套解析

给所有嵌套类加上@dataclass装饰器,并编写递归解析函数,把字典逐层转换成对应的类实例:

import json
from dataclasses import dataclass, asdict

@dataclass
class GradeDetails:
    first_term: str
    second_term: str
    pass_or_fail: str

@dataclass
class SubjectDetails:
    subject_name: str
    term_score: GradeDetails

@dataclass
class Student:
    name: str
    roll_number: str
    grade_class: str
    subjects: SubjectDetails

def dict_to_instance(data, cls):
    """递归将字典转换为dataclass实例"""
    if hasattr(cls, '__annotations__'):
        field_types = cls.__annotations__
        processed_data = {}
        for field, type_cls in field_types.items():
            value = data.get(field)
            if isinstance(value, dict):
                processed_data[field] = dict_to_instance(value, type_cls)
            else:
                processed_data[field] = value
        return cls(**processed_data)
    return data

def json_to_json_string():
    json_data = '''
    {
      "name": "John Doe",
      "roll_number": "123456",
      "grade_class": "10th Grade",
      "subjects": 
        {
          "subject_name": "Math",
          "term_score": {
            "first_term": "A",
            "second_term": "B",
            "pass_or_fail": "Pass"
          }
        }
      
    }
    '''
    parsed_data = json.loads(json_data)
    return parsed_data

if __name__ == '__main__':
    data_dict = json_to_json_string()
    student_data = dict_to_instance(data_dict, Student)
    student_subject = student_data.subjects

    print(f" student data :: \n {student_data} \n")
    print(f" subject details are :: \n {student_subject.subject_name} \n")
    # 也可以轻松转回JSON
    print(json.dumps(asdict(student_data), indent=2))

方案2:使用Pydantic(更推荐,接近Scala的类型安全JSON解析)

Pydantic是专门用于数据验证和JSON序列化/反序列化的库,能自动处理嵌套类的解析、类型校验,完全符合你想要的类似Scala模式匹配的类型安全效果:
首先安装Pydantic:

pip install pydantic

然后修改代码:

import json
from pydantic import BaseModel

class GradeDetails(BaseModel):
    first_term: str
    second_term: str
    pass_or_fail: str

class SubjectDetails(BaseModel):
    subject_name: str
    term_score: GradeDetails

class Student(BaseModel):
    name: str
    roll_number: str
    grade_class: str
    subjects: SubjectDetails

def json_to_json_string():
    json_data = '''
    {
      "name": "John Doe",
      "roll_number": "123456",
      "grade_class": "10th Grade",
      "subjects": 
        {
          "subject_name": "Math",
          "term_score": {
            "first_term": "A",
            "second_term": "B",
            "pass_or_fail": "Pass"
          }
        }
      
    }
    '''
    parsed_data = json.loads(json_data)
    return parsed_data

if __name__ == '__main__':
    data_dict = json_to_json_string()
    student_data = Student(**data_dict)
    student_subject = student_data.subjects

    print(f" student data :: \n {student_data} \n")
    print(f" subject details are :: \n {student_subject.subject_name} \n")
    # 直接转JSON字符串
    print(student_data.model_dump_json(indent=2))

Pydantic还支持自动校验字段类型、缺失字段处理、默认值等功能,比手动写dataclass解析更健壮,是Python中实现类型安全JSON解析的首选方案。

内容的提问来源于stack exchange,提问作者Sarkuna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:30:40