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

Python中JSON反序列化复杂类对象的问题及修正方案

Python JSON序列化/反序列化复杂类问题解决

问题描述

使用Python的json包实现自定义类(FirstStandard和Student)的序列化与反序列化时,序列化可以成功生成包含多个学生的JSON字符串,但反序列化后无法得到完整的学生列表,实际仅得到单个嵌套的对象结构。

原类定义

class FirstStandard:
    def __init__(self, student=None):
        self.students = []
        if student:
            self.students.append(student.__dict__)

    def toJson(self):
        return vars(self)

    def update(self, student):
        if student:
           self.students.append(student.__dict__)

class Student:
    def __init__(self, sid, fName, lName, fee):
        self.sid = sid
        self.fName = fName
        self.lName = lName
        self.fee = fee

原测试代码

def student_hook(stu_dict):
    return FirstStandard(stu_dict['students'])


if __name__ == '__main__':
    s = Student(10, 'ABC', 'XYZ', 12345)
    studs = FirstStandard(s)
    s1 = Student(11, 'AAA', 'BBB', 99999)
    studs.update(s1)

    # serialization
    message = json.dumps(studs.toJson())
    print(message)

    # deserialization
    x = json.loads(message, object_hook=student_hook)
    print(x.students)

问题原因

  1. FirstStandard的__init__方法仅支持接收单个Student对象,并将其转成字典后添加到students列表;但反序列化时,stu_dict['students']是一个包含多个学生字典的列表,此时__init__会把整个列表作为单个元素添加到self.students,导致最终students变成嵌套列表(如[[dict1, dict2]]),而非预期的平级列表。
  2. 原object_hook未将学生字典还原为Student实例,直接传递给FirstStandard,导致结构不匹配。

解决方案

方案1:修改FirstStandard初始化逻辑+优化object_hook

首先调整FirstStandard的__init__,使其支持接收单个Student对象或学生字典/对象的列表:

class FirstStandard:
    def __init__(self, students=None):
        self.students = []
        if students:
            # 处理单个Student对象
            if isinstance(students, Student):
                self.students.append(students.__dict__)
            # 处理学生列表(支持Student对象或字典)
            elif isinstance(students, list):
                for item in students:
                    if isinstance(item, Student):
                        self.students.append(item.__dict__)
                    elif isinstance(item, dict):
                        self.students.append(item)

    def toJson(self):
        return vars(self)

    def update(self, student):
        if student:
           self.students.append(student.__dict__)

然后修改object_hook,将每个学生字典还原为Student实例后再传入FirstStandard:

def student_hook(stu_dict):
    # 遍历学生字典列表,生成Student实例并转成对应字典结构
    student_list = []
    for s_data in stu_dict['students']:
        student = Student(s_data['sid'], s_data['fName'], s_data['lName'], s_data['fee'])
        student_list.append(student.__dict__)
    return FirstStandard(student_list)

方案2:给Student添加类方法简化反序列化

为Student添加from_dict类方法,更优雅地从字典生成实例:

class Student:
    def __init__(self, sid, fName, lName, fee):
        self.sid = sid
        self.fName = fName
        self.lName = lName
        self.fee = fee

    @classmethod
    def from_dict(cls, data):
        """从字典生成Student实例"""
        return cls(data['sid'], data['fName'], data['lName'], data['fee'])

此时object_hook可以简化为:

def student_hook(stu_dict):
    # 生成Student实例列表后传入FirstStandard
    student_instances = [Student.from_dict(s) for s in stu_dict['students']]
    return FirstStandard(student_instances)

测试验证

修改后运行测试代码,反序列化后的x.students会输出预期的平级学生字典列表:

[{'sid': 10, 'fName': 'ABC', 'lName': 'XYZ', 'fee': 12345}, {'sid': 11, 'fName': 'AAA', 'lName': 'BBB', 'fee': 99999}]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:05:33