如何将字典/列表转换为Ignition Perspective Tree组件结构?
字典/列表转Ignition Perspective Tree视图格式问题
需求
需要将给定的字典数据转换为Ignition Perspective Tree组件所需的层级结构,当前代码生成的结果中sub-complex2.barrels部分的树分支不符合要求,缺失了带索引的父节点。
原始数据
{ 'barrelIds': ['BOB', 'SARAH'], 'executionMode': 'EMPTY_FILL', 'emptyRequest': { 'barrelGroupId': 123458, 'requestId': 7832 }, 'complex': { 'sub-complex': ['BOB', 'SARAH'], 'sub-complex2': { 'barrelGroupId': 123458, 'barrels': [{ 'item': 1 }, { 'item': 2 } ] } } }
目标Tree结构
[ { "label": "barrelIds", "expanded": true, "items": [ { "label": "BOB", "expanded": true, "items": [] }, { "label": "SARAH", "expanded": true, "items": [] } ] }, { "label": "executionMode = 'EMPTY_FILL'", "expanded": true, "items": [] }, { "label": "emptyRequest", "expanded": true, "items": [ { "label": "barrelGroupId = 123458", "expanded": true, "items": [] }, { "label": "requestId = 7832", "expanded": true, "items": [] } ] }, { "label": "complex", "expanded": true, "items": [ { "label": "sub-complex", "expanded": true, "items": [ { "label": "BOB", "expanded": false, "items": [] }, { "label": "SARAH", "expanded": false, "items": [] } ] }, { "label": "sub-complex2", "expanded": true, "items": [ { "label": "barrelGroupId = 123458", "expanded": true, "items": [] }, { "label": "barrels", "expanded": true, "items": [ { "label": "[0]", "expanded": true, "items": [ { "label": "item = 1", "expanded": false, "items": [] } ] }, { "label": "[1]", "expanded": true, "items": [ { "label": "item = 2", "expanded": true, "items": [] } ] } ] } ] } ] } ]
转换核心规则
- 每个树分支格式为:
{'label': '', 'items': [], 'expanded': True} - 字典键值对中,值为基础类型(数值、字符串等)时:
{'label': '{} = {}'.format(key, repr(value)), 'items': [], 'expanded': True} - 字典键值对中,值为字典/列表时:
{'label': key, 'items': [子节点列表], 'expanded': True} - 列表中元素为基础类型时:
{'label': value, 'items': [], 'expanded': True} - 列表中元素为字典/列表时:
{'label': '[索引]', 'items': [子节点列表], 'expanded': True}
当前实现代码
def get_tree_items(data): # TODO: # 1. simplify this. top conditions shouldn't have sub-fors. # 2. empty dicts are not handled. if isinstance(data, dict): items = [] for key, value in data.items(): if isinstance(value, list): sub_items = get_tree_items(value) items.append(format_value(key, value, sub_items)) elif isinstance(value, dict): sub_items = get_tree_items(value) items.append(format_value(key, value, sub_items)) else: items.append({'label': '{} = {}'.format(key, repr(value)), 'items': [], 'expanded': True}) return items elif isinstance(data, list): items = [] for idx, item in enumerate(data): new_item = get_tree_items(item) items.append(new_item) return items else: return {'label': data, 'items': [], 'expanded': True} def format_value(key, value, sub_items): if isinstance(sub_items, list): return {'label': key, 'items': sub_items, 'expanded': True} else: return {'label': '{} = {}'.format(key, value), 'items': [], 'expanded': True}
当前错误输出
[{ 'label': 'barrelIds', 'items': [{ 'label': 'BOB', 'items': [], 'expanded': True }, { 'label': 'SARAH', 'items': [], 'expanded': True } ], 'expanded': True }, { 'label': "executionMode = 'EMPTY_FILL'", 'items': [], 'expanded': True }, { 'label': 'emptyRequest', 'items': [{ 'label': 'barrelGroupId = 123458', 'items': [], 'expanded': True }, { 'label': 'requestId = 7832', 'items': [], 'expanded': True } ], 'expanded': True }, { 'label': 'complex', 'items': [{ 'label': 'sub-complex', 'items': [{ 'label': 'BOB', 'items': [], 'expanded': True }, { 'label': 'SARAH', 'items': [], 'expanded': True } ], 'expanded': True }, { 'label': 'sub-complex2', 'items': [{ 'label': 'barrelGroupId = 123458', 'items': [], 'expanded': True }, { 'label': 'barrels', 'items': [[{ 'label': 'item = 1', 'items': [], 'expanded': True } ], [{ 'label': 'item = 2', 'items': [], 'expanded': True } ]], 'expanded': True } ], 'expanded': True } ], 'expanded': True } ]
问题点:barrels的items直接嵌套了子节点列表,没有生成带[0]、[1]索引的父节点,导致Tree视图中分支缺失。
修复后的代码
def build_tree(data): nodes = [] if isinstance(data, dict): for key, value in data.items(): child_nodes = build_tree(value) if isinstance(value, (dict, list)): # 处理值为字典/列表的情况,生成父节点 nodes.append({ "label": key, "expanded": True, "items": child_nodes }) else: # 处理值为基础类型的情况,生成"key = value"节点 nodes.append({ "label": f"{key} = {repr(value)}", "expanded": True, "items": [] }) elif isinstance(data, list): for idx, item in enumerate(data): child_nodes = build_tree(item) if isinstance(item, (dict, list)): # 列表元素为复杂类型,生成带索引的父节点 nodes.append({ "label": f"[{idx}]", "expanded": True, "items": child_nodes }) else: # 列表元素为基础类型,直接生成节点 nodes.append({ "label": item, "expanded": True, "items": [] }) else: # 单独的基础类型,生成节点 nodes.append({ "label": data, "expanded": True, "items": [] }) return nodes # 使用示例 original_data = { 'barrelIds': ['BOB', 'SARAH'], 'executionMode': 'EMPTY_FILL', 'emptyRequest': { 'barrelGroupId': 123458, 'requestId': 7832 }, 'complex': { 'sub-complex': ['BOB', 'SARAH'], 'sub-complex2': { 'barrelGroupId': 123458, 'barrels': [{'item': 1}, {'item': 2}] } } } tree_structure = build_tree(original_data)
修复说明
- 统一函数返回值为节点列表,避免混合返回单个节点和列表导致的嵌套错误。
- 针对列表元素做区分处理:
- 若元素是基础类型,直接生成以元素值为
label的节点。 - 若元素是字典/列表,生成以
[索引]为label的父节点,将元素处理后的子节点列表作为该节点的items。
- 若元素是基础类型,直接生成以元素值为
- 简化逻辑,去掉额外的
format_value函数,直接在分支判断中生成对应节点格式。
内容的提问来源于stack exchange,提问作者njminchin
相关产品推荐
相关产品推荐

