如何对比符合Schema的Ignition SCADA标签JSON文件?
Ignition SCADA标签JSON对比与变更报告生成
问题概述
我有Ignition SCADA的标签配置JSON文件,结构为树形:终端节点是带配置信息的标签,非终端节点是文件夹,每个文件夹通过tags字段包含子标签或子文件夹。标签的唯一标识是完整路径,由所在文件夹的name字段依次拼接,用/分隔(例如StackOverflow/FolderA/TagA)。
已完成的标签修改:
- 新增标签:
StackOverflow/FolderA/TagC - 修改标签:
StackOverflow/FolderA/TagA的tooltip值 - 修改标签:
StackOverflow/FolderA/TagA的value值 - 删除标签:
StackOverflow/FolderA/TagB
需要生成符合以下格式的变更报告,最终导出到Excel:
[ {'tagpath': 'StackOverflow/FolderA/TagC', 'changedFrom': None, 'changedTo': 'added'}, {'tagpath': 'StackOverflow/FolderA/TagA.tooltip', 'changedFrom': 'This is tag a', 'changedTo': 'This is tag a with changes'}, {'tagpath': 'StackOverflow/FolderA/TagA.value', 'changedFrom': 15, 'changedTo': 59}, {'tagpath': 'StackOverflow/FolderA/TagB', 'changedFrom': None, 'changedTo': 'deleted'} ]
目前用手动for循环对比效率低,想找Python中更高效专业的实现方法。
高效实现方案
核心思路是先把嵌套的树形结构扁平化为以完整路径为键的字典,再通过集合操作和字段对比快速找出差异,最后生成标准化报告并导出Excel。
1. 树形结构扁平化
写一个递归函数,遍历嵌套的标签/文件夹,生成完整路径到标签配置的映射:
def flatten_tags(tag_tree, parent_path=""): flattened = {} for item in tag_tree: current_path = f"{parent_path}/{item['name']}" if parent_path else item['name'] # 判断是文件夹还是终端标签 if 'tags' in item: # 递归处理子文件夹 flattened.update(flatten_tags(item['tags'], current_path)) else: # 终端标签直接存入字典 flattened[current_path] = item return flattened
2. 对比两个扁平化字典
分别加载修改前、修改后的JSON文件,扁平化后通过集合操作快速定位差异路径:
import json # 加载前后版本的标签JSON with open('old_tags.json', 'r') as f: old_tree = json.load(f)['tags'] with open('new_tags.json', 'r') as f: new_tree = json.load(f)['tags'] # 扁平化处理 old_flat = flatten_tags(old_tree) new_flat = flatten_tags(new_tree) # 快速找出新增、删除、共同的标签路径 added_paths = new_flat.keys() - old_flat.keys() deleted_paths = old_flat.keys() - new_flat.keys() common_paths = old_flat.keys() & new_flat.keys()
3. 生成变更报告
遍历三类路径,生成符合要求的报告条目:
change_report = [] # 处理新增标签 for path in added_paths: change_report.append({ 'tagpath': path, 'changedFrom': None, 'changedTo': 'added' }) # 处理删除标签 for path in deleted_paths: change_report.append({ 'tagpath': path, 'changedFrom': None, 'changedTo': 'deleted' }) # 处理标签字段修改 for path in common_paths: old_config = old_flat[path] new_config = new_flat[path] # 对比所有键值对,找出变更字段 for key in set(old_config.keys()).union(new_config.keys()): old_val = old_config.get(key, None) new_val = new_config.get(key, None) if old_val != new_val: change_report.append({ 'tagpath': f"{path}.{key}", 'changedFrom': old_val, 'changedTo': new_val })
4. 导出到Excel
用pandas快速导出报告到Excel,格式规范且支持后续编辑:
import pandas as pd df = pd.DataFrame(change_report) df.to_excel('tag_changes_report.xlsx', index=False)
优势说明
- 扁平化处理将嵌套结构转为一维字典,避免多层循环嵌套,对比逻辑更简洁
- 集合操作(
-/&)比手动遍历找差异效率更高,尤其适合标签数量大的场景 - 递归扁平化函数适配任意深度的文件夹结构,扩展性强
- pandas导出的Excel格式规范,支持后续筛选、排序等操作
内容的提问来源于stack exchange,提问作者njminchin
相关产品推荐
相关产品推荐

