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

如何用Python合并含多层属性及数组的JSON对象?

我太懂这种踩坑的感觉了——处理带数组的JSON合并可比单纯的平面对象合并麻烦多了,直接覆盖整个数组肯定不是你想要的结果。咱们来一步步解决这个问题:

解决方案思路与代码实现

先明确场景(举个例子)

假设你的原JSON文件(original.json)结构是这样的:

{
  "app_name": "My Project",
  "configurations": [
    {
      "env": "dev",
      "api_url": "http://old-dev-api.com",
      "timeout": 30,
      "nested": {
        "old_key": "keep this"
      }
    },
    {
      "env": "prod",
      "api_url": "http://prod-api.com"
    }
  ],
  "global_setting": "retain me"
}

你要合并的更新JSON(update.json)是:

{
  "configurations": [
    {
      "env": "dev",
      "api_url": "http://new-dev-api.com",
      "debug_mode": true,
      "nested": {
        "new_key": "add this"
      }
    },
    {
      "env": "staging",
      "api_url": "http://staging-api.com"
    }
  ],
  "new_global_setting": "added value"
}

你的需求是:

  • 全局属性:保留原有app_name、global_setting,新增new_global_setting
  • configurations数组:
    • 匹配env为dev的项:替换api_url,新增debug_mode,合并嵌套的nested属性(保留原有old_key,添加new_key)
    • 保留env为prod的原有项
    • 添加env为staging的新项

核心思路

  1. 递归合并字典:处理多层嵌套的属性,实现“替换已有键、添加缺失键”的需求,而不是直接覆盖整个子字典。
  2. 数组项匹配合并:通过数组项的唯一标识(比如示例中的env)找到对应项,合并属性;同时保留原数组中未被更新的项,添加新的项。

完整Python代码

import json

def merge_dicts(target, source):
    """递归合并两个字典:用source的键值替换target已有键,添加target没有的键(支持嵌套)"""
    for key, value in source.items():
        if isinstance(value, dict) and key in target and isinstance(target[key], dict):
            # 嵌套字典,递归处理
            merge_dicts(target[key], value)
        else:
            # 普通键,直接替换或添加
            target[key] = value
    return target

def merge_array_by_key(original_array, update_array, unique_key='env'):
    """
    合并两个数组:根据指定的唯一键匹配项,合并属性;保留原数组未被更新的项,添加新项
    :param original_array: 原JSON中的数组
    :param update_array: 更新JSON中的数组
    :param unique_key: 数组项的唯一标识键(比如'id'、'env')
    """
    # 把原数组转成字典,用唯一键做key,方便快速查找
    original_dict = {item[unique_key]: item for item in original_array}
    
    # 遍历更新数组,合并或添加项
    for item in update_array:
        item_key = item[unique_key]
        if item_key in original_dict:
            # 已有项,合并属性
            merge_dicts(original_dict[item_key], item)
        else:
            # 新项,直接加入字典
            original_dict[item_key] = item
    
    # 保持原数组的顺序,再追加新增的项(如果不需要顺序,直接返回list(original_dict.values())即可)
    merged_array = []
    # 先加入原数组中存在的项(保留原顺序)
    for item in original_array:
        merged_array.append(original_dict[item[unique_key]])
    # 加入更新数组中新增的项(不在原数组里的)
    original_keys = {item[unique_key] for item in original_array}
    update_keys = {item[unique_key] for item in update_array}
    new_keys = update_keys - original_keys
    for item in update_array:
        if item[unique_key] in new_keys:
            merged_array.append(item)
    
    return merged_array

def main():
    # 加载原JSON
    with open('original.json', 'r', encoding='utf-8') as f:
        original_data = json.load(f)
    
    # 加载更新JSON
    with open('update.json', 'r', encoding='utf-8') as f:
        update_data = json.load(f)
    
    # 先把更新数据中的数组单独拿出来,避免被全局合并覆盖
    update_configs = update_data.pop('configurations', [])
    
    # 合并全局属性(替换已有,添加缺失)
    merge_dicts(original_data, update_data)
    
    # 合并configurations数组
    original_configs = original_data.get('configurations', [])
    merged_configs = merge_array_by_key(original_configs, update_configs, unique_key='env')
    original_data['configurations'] = merged_configs
    
    # 保存合并后的JSON
    with open('merged.json', 'w', encoding='utf-8') as f:
        json.dump(original_data, f, indent=2, ensure_ascii=False)

if __name__ == '__main__':
    main()

关键说明

  1. 递归字典合并:merge_dicts函数会处理多层嵌套的字典,比如示例中dev项的nested属性,会保留原有old_key并添加new_key,而不是直接覆盖整个nested字典。
  2. 数组匹配逻辑:merge_array_by_key函数通过唯一键(比如env)匹配数组项,确保已有项的属性被合并而非替换,同时保留原数组中未被更新的项(比如prod),并添加新项(比如staging)。
  3. 自定义调整:如果你的数组唯一标识不是env,只需要修改merge_array_by_key调用时的unique_key参数即可;如果不需要保留原数组的顺序,可以简化数组合并的逻辑,直接返回list(original_dict.values())。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:03:56