You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Groovy/JavaScript中对比JSON并输出原格式差异

问题:JSON对比需保留原层级结构并标记变更节点

需要对比两个JSON对象,输出与输入JSON格式完全一致的差异结果。例如仅修改L2_Entity_Nm字段值时,期望输出保留原JSON的层级结构,并在发生变更的节点上添加"operation": "UPDATED"字段。但当前参考代码运行后返回的是Difference对象列表格式,不符合预期,需调整代码实现目标。


解决方案:递归遍历对比,构建层级化差异结果

核心思路是递归遍历两个JSON的每一层节点,逐层对比值并保留原结构,仅在变更节点添加标记:

  • 遇到对象类型节点:递归对比其子节点,仅保留存在变更的子结构;
  • 遇到数组类型节点:按索引逐一对比元素(复杂场景可根据唯一标识匹配);
  • 节点值发生变更:在该节点下添加"operation": "UPDATED"字段;
  • 无变更的节点不纳入最终结果。

代码实现(Python)

def compare_json(old_json, new_json):
    diff = {}

    # 处理新增、更新的节点
    for key in new_json:
        old_val = old_json.get(key)
        new_val = new_json[key]

        if old_val is None:
            # 新增节点,标记为ADDED(可按需调整)
            diff[key] = {**(new_val if isinstance(new_val, dict) else {"value": new_val}), "operation": "ADDED"}
        elif isinstance(old_val, dict) and isinstance(new_val, dict):
            # 递归对比子对象
            sub_diff = compare_json(old_val, new_val)
            if sub_diff:
                diff[key] = sub_diff
        elif isinstance(old_val, list) and isinstance(new_val, list):
            # 数组对比:按索引逐一检查
            arr_diff = []
            max_len = max(len(old_val), len(new_val))
            for i in range(max_len):
                old_item = old_val[i] if i < len(old_val) else None
                new_item = new_val[i] if i < len(new_val) else None

                if old_item is None:
                    arr_diff.append({**(new_item if isinstance(new_item, dict) else {"value": new_item}), "operation": "ADDED"})
                elif new_item is None:
                    arr_diff.append({**(old_item if isinstance(old_item, dict) else {"value": old_item}), "operation": "REMOVED"})
                elif isinstance(old_item, dict) and isinstance(new_item, dict):
                    item_diff = compare_json(old_item, new_item)
                    if item_diff:
                        arr_diff.append(item_diff)
                elif old_item != new_item:
                    arr_diff.append({"value": new_item, "operation": "UPDATED"})
            if arr_diff:
                diff[key] = arr_diff
        elif old_val != new_val:
            # 值变更,添加UPDATED标记
            diff[key] = {"value": new_val, "operation": "UPDATED"}

    # 处理被删除的节点
    for key in old_json:
        if key not in new_json:
            diff[key] = {**(old_json[key] if isinstance(old_json[key], dict) else {"value": old_json[key]}), "operation": "REMOVED"}

    return diff

测试示例

输入旧JSON:

{
  "L1_Entity": {
    "L1_Entity_Nm": "总部",
    "L2_Entity": {
      "L2_Entity_Nm": "技术部",
      "Staff_Count": 50
    }
  }
}

输入新JSON:

{
  "L1_Entity": {
    "L1_Entity_Nm": "总部",
    "L2_Entity": {
      "L2_Entity_Nm": "研发部",
      "Staff_Count": 50
    }
  }
}

输出结果:

{
  "L1_Entity": {
    "L2_Entity": {
      "L2_Entity_Nm": {
        "value": "研发部",
        "operation": "UPDATED"
      }
    }
  }
}

可调整点

  • 如果希望将变更值与operation放在同一层级(而非嵌套value),可修改基本类型值的处理逻辑(注意字符串、数字等基本类型无法直接添加键,需转为字典结构);
  • 数组对比若需根据对象唯一标识(如id)匹配而非索引,可修改数组遍历逻辑,先通过唯一键关联新旧元素再对比;
  • 可按需扩展operation类型,比如ADDED、REMOVED来覆盖更多场景;
  • 对于null、日期等特殊类型,需额外添加判断逻辑确保对比准确。

内容的提问来源于stack exchange,提问作者user22174139

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 22:22:53