基于API数据构建嵌套字典并序列化至JSON的技术问询
解决方案:从API数据构建指定嵌套JSON结构
嘿,你的思路已经很到位了!用三层循环遍历API返回的嵌套数据,再通过setdefault逐层搭建嵌套字典,完全符合JSON结构化存储的需求。我来帮你把这个实现补全,再分享几个优化点和注意事项:
1. 现有代码的核心逻辑解析
你写的这段代码最大的优势是用dict.setdefault()安全地逐层创建嵌套结构——它会自动检查键是否存在,不存在就创建默认值(空字典/空数组),完美避免了繁琐的if key not in dict判断,让代码简洁又健壮。
最终生成的结构完全匹配你需要的嵌套JSON:
- 顶层是
university键 - 下一层是学校标识(
str(elem_a)) - 再下一层是二级分类(比如院系,
str(elem_b)) - 最底层是
student数组,存放每个学生的信息字典
2. 完整实现(含JSON文件写入)
你的代码已经完成了字典构建,只需要补充将字典写入JSON文件的步骤。这里给出完整的可运行代码:
import json # 替换为你从API获取的原始数据列表 list_a = [...] my_dict = {} for elem_a in list_a: for elem_b in elem_a: for elem_c in elem_b: # 提取学生核心信息 elem_c_info = { "name" : elem_c.prop1, "ID" : elem_c.prop2, "GPA" : elem_c.prop3 } # 逐层构建嵌套字典,确保每个层级都存在 my_dict.setdefault("university", {}) \ .setdefault(str(elem_a), {}) \ .setdefault(str(elem_b), {}) \ .setdefault("student", []).append(elem_c_info) # 将字典写入JSON文件,格式化输出提升可读性 with open("university_students.json", "w", encoding="utf-8") as f: json.dump(my_dict, f, indent=4, ensure_ascii=False)
代码说明:
json.dump()的indent=4参数会让JSON文件以缩进格式输出,方便阅读和调试ensure_ascii=False确保中文等非ASCII字符能正确保存,不会被转成Unicode编码
3. 可选优化:用collections.defaultdict简化嵌套代码
如果觉得多层setdefault的链式调用有点冗长,可以用collections.defaultdict来定义递归的嵌套结构,让代码更直观:
from collections import defaultdict import json # 定义递归的defaultdict,自动创建嵌套字典 def nested_defaultdict(): return defaultdict(nested_defaultdict) my_dict = nested_defaultdict() for elem_a in list_a: for elem_b in elem_a: for elem_c in elem_b: elem_c_info = { "name" : elem_c.prop1, "ID" : elem_c.prop2, "GPA" : elem_c.prop3 } # 直接赋值,无需手动检查层级是否存在 my_dict["university"][str(elem_a)][str(elem_b)]["student"].append(elem_c_info) # 注意:defaultdict不能直接被JSON序列化,需要转成普通字典 my_dict = dict(my_dict) # 写入JSON文件 with open("university_students.json", "w", encoding="utf-8") as f: json.dump(my_dict, f, indent=4, ensure_ascii=False)
4. 关键注意事项
- 键的字符串转换:你用
str(elem_a)和str(elem_b)是非常必要的!JSON要求所有键必须是字符串类型,如果elem_a/elem_b是对象或数字,直接作为键会导致序列化失败,转成字符串能避免这个问题。 - 数据类型兼容性:确保API返回的
elem_c.prop1/prop2/prop3都是JSON支持的类型(字符串、数字、布尔值),如果有datetime等特殊类型,需要先转成字符串(比如elem_c.prop3.strftime("%Y-%m-%d"))。 - 空数据清理:如果某些层级下没有学生数据,
setdefault会自动创建空的student数组。如果需要避免空数组,可以在写入JSON前遍历字典,删除空的student列表。
内容的提问来源于stack exchange,提问作者Shawn
相关产品推荐
相关产品推荐

