Python解析JSON构建层级分类结构并导出CSV方法
实现思路
- 放弃用正则从字符串转义结果里匹配id的方案,直接遍历JSON中
businessModelInfo的键值对,构建以节点id为key的节点映射字典,字典值存储节点的name和parentId,这种方式查询效率为O(1),也不会出现正则匹配漏值、错值的问题。 - 对每个节点做向上溯源:从当前节点出发,用循环/递归查找父节点,直到碰到parentId为空、或者parentId不在节点映射字典里的根节点为止,把沿途收集到的节点名称按「根节点→父节点→当前节点」的顺序排列,用
>拼接成完整层级路径。 - 增加路径缓存逻辑:如果某一个节点的完整路径已经计算过,后续它的子节点溯源时直接复用已计算的父路径,不用每次都回溯到根节点,大幅提升多层级数据的处理效率。
- 所有节点路径计算完成后,用Python内置的csv模块把节点id、节点名称、完整层级路径写入目标CSV,文件编码选
utf-8-sig避免Excel打开中文乱码。
参考实现代码
import json import csv # 1. 读取JSON构建节点映射 node_map = {} # key: 节点id, value: {"name": 节点名, "parentId": 父节点id} with open(r'C:\Users\UserName\CodeProjects\project_one\test.json', 'r', encoding='utf-8') as f: data = json.load(f) biz_info = data.get('businessModelInfo', {}) for node_id, node_info in biz_info.items(): node_map[node_id] = { "name": node_info.get("name", ""), "parentId": node_info.get("parentId", "") } # 2. 带缓存计算每个节点的完整路径 path_cache = {} def get_full_path(node_id): # 已经计算过的路径直接返回缓存结果 if node_id in path_cache: return path_cache[node_id] # 节点不存在直接返回空字符串 if node_id not in node_map: return "" current_node = node_map[node_id] parent_id = current_node["parentId"] # 根节点判定:parentId为空 或者 父id不在当前节点映射表中 if not parent_id or parent_id not in node_map: full_path = current_node["name"] else: parent_path = get_full_path(parent_id) full_path = f"{parent_path} > {current_node['name']}" # 结果写入缓存 path_cache[node_id] = full_path return full_path # 3. 批量计算所有节点的完整层级 result = [] for nid, info in node_map.items(): result.append({ "id": nid, "name": info["name"], "parentId": info["parentId"], "full_path": get_full_path(nid) }) # 4. 结果写入CSV文件 with open(r'C:\Users\UserName\CodeProjects\project_one\category_output.csv', 'w', encoding='utf-8-sig', newline='') as f: writer = csv.DictWriter(f, fieldnames=["id", "name", "parentId", "full_path"]) writer.writeheader() writer.writerows(result)
代码运行后输出的CSV中,
full_path列就是需要的类似Cybersecurity > Network Security > NIDS > Honeypot格式的完整层级路径。如果数据存在循环父引用(比如A的父节点是B,B的父节点是A),可以在递归函数里增加访问集合标记,避免死循环。
内容的提问来源于stack exchange,提问作者BQuist
相关产品推荐
相关产品推荐

