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)
问题原因
FirstStandard的__init__方法仅支持接收单个Student对象,并将其转成字典后添加到students列表;但反序列化时,stu_dict['students']是一个包含多个学生字典的列表,此时__init__会把整个列表作为单个元素添加到self.students,导致最终students变成嵌套列表(如[[dict1, dict2]]),而非预期的平级列表。- 原
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
相关产品推荐
相关产品推荐

