如何实现支持多层子节点的JSON菜单指定节点链提取?
多级嵌套JSON菜单节点提取方案
需求说明
根据传入的节点链列表,从给定的多级嵌套JSON菜单结构中提取指定节点,忽略未在列表中的节点,生成新的JSON对象。节点链中的“.”表示层级关系,需保留该节点的所有子节点及完整父层级结构。
给定的Master JSON
{ "menustructure": [ { "node": "Admin", "path": "admin", "child": [ { "id": "resouce0", "node": "Admin.resouce0", "path": "resouce0", "rank": 0, "child": [ { "id": "res_child", "node": "Admin.resouce0.res_child", "path": "res_child", "rank": 1 }, { "id": "res_child2", "node": "Admin.resouce0.res_child2", "path": "res_child", "rank": 1 } ] }, { "id": "resouce1", "node": "Admin.resouce1", "path": "resouce1", "rank": 1 }, { "id": "resouce2", "node": "Admin.resouce2", "path": "oath", "rank": 2 } ] }, { "node": "Workspace", "path": "wsp", "child": [ { "id": "system1", "node": "Workspace.system1", "path": "sys1", "child": [ { "id": "child1", "node": "Workspace.system1.child1", "path": "ch1" } ] }, { "id": "system2", "node": "Workspace.system2", "path": "sys2" } ] } ] }
示例说明
- 传入节点链
['Admin.resouce1', 'Workspace']:生成包含Admin.resouce1节点(带完整Admin父层级)和整个Workspace节点(含所有子节点)的新JSON - 传入节点链
['Admin.resouce2', 'Workspace.system1']:提取Admin.resouce2(带Admin父层级)和Workspace.system1(带Workspace父层级及自身子节点) - 传入节点链
['Admin']:提取完整的Admin节点及其所有子节点
现有代码问题
现有代码仅支持一级子节点提取,无法处理master->child->child或更深层级的节点提取;同时父节点已存在时的子节点追加逻辑不完善,尝试过glom库未达预期。
解决方案
采用递归遍历+目标节点集合的方式,支持任意深度的嵌套节点提取,同时自动维护父层级结构:
import json import copy def extract_menu_nodes(master_menu, target_node_paths): # 收集所有需要保留的节点(包括目标节点的所有父节点) target_nodes = set() for path in target_node_paths: parts = path.split('.') # 生成每个节点链的所有层级路径,确保父节点被保留 for i in range(1, len(parts) + 1): full_node_path = '.'.join(parts[:i]) target_nodes.add(full_node_path) # 递归过滤节点 def filter_recursive(node): # 当前节点不在目标集合中,直接丢弃 if node['node'] not in target_nodes: return None # 复制节点,避免修改原始数据 filtered_node = copy.deepcopy(node) # 处理子节点 if 'child' in filtered_node and filtered_node['child']: filtered_children = [] for child in filtered_node['child']: processed_child = filter_recursive(child) if processed_child: filtered_children.append(processed_child) # 更新子节点列表,无符合条件的子节点则移除child字段 if filtered_children: filtered_node['child'] = filtered_children else: del filtered_node['child'] return filtered_node # 处理根节点列表 filtered_menus = [] for root_node in master_menu['menustructure']: filtered_root = filter_recursive(root_node) if filtered_root: filtered_menus.append(filtered_root) return {'menustructure': filtered_menus} # 测试示例 if __name__ == "__main__": # 加载原始Master JSON master_json = """ { "menustructure": [ { "node": "Admin", "path": "admin", "child": [ { "id": "resouce0", "node": "Admin.resouce0", "path": "resouce0", "rank": 0, "child": [ { "id": "res_child", "node": "Admin.resouce0.res_child", "path": "res_child", "rank": 1 }, { "id": "res_child2", "node": "Admin.resouce0.res_child2", "path": "res_child", "rank": 1 } ] }, { "id": "resouce1", "node": "Admin.resouce1", "path": "resouce1", "rank": 1 }, { "id": "resouce2", "node": "Admin.resouce2", "path": "oath", "rank": 2 } ] }, { "node": "Workspace", "path": "wsp", "child": [ { "id": "system1", "node": "Workspace.system1", "path": "sys1", "child": [ { "id": "child1", "node": "Workspace.system1.child1", "path": "ch1" } ] }, { "id": "system2", "node": "Workspace.system2", "path": "sys2" } ] } ] } """ master_menu = json.loads(master_json) # 测试示例1:提取Admin.resouce1和Workspace targets1 = ['Admin.resouce1', 'Workspace'] result1 = extract_menu_nodes(master_menu, targets1) print("示例1结果:") print(json.dumps(result1, indent=2)) # 测试示例2:提取Admin.resouce2和Workspace.system1 targets2 = ['Admin.resouce2', 'Workspace.system1'] result2 = extract_menu_nodes(master_menu, targets2) print("\n示例2结果:") print(json.dumps(result2, indent=2)) # 测试示例3:提取Admin targets3 = ['Admin'] result3 = extract_menu_nodes(master_menu, targets3) print("\n示例3结果:") print(json.dumps(result3, indent=2))
方案优势
- 递归处理逻辑,支持任意深度的嵌套节点提取
- 自动收集目标节点的所有父层级,确保结构完整性
- 仅保留目标节点及其子节点,自动过滤无关节点
- 避免重复添加父节点,递归过程中自然完成父节点的合并
内容的提问来源于stack exchange,提问作者vineet singh
相关产品推荐
相关产品推荐

