Python中有什么好的办法比较两个JSON列表的差异?

有 list A 与 list B,list 中的每一个元素是一个 JSON 对象,请问有什么好的方式来比较两个 list 中存在差异的部分呢?

例如:

list A:[json1, json2, josn3]

list B:[json1, json2, josn3]

我想要比较这两个 list 是否完全一样或者存在着怎样的差异,请问最好的解决方式是什么?


Python中有什么好的办法比较两个JSON列表的差异?
16 回复

把 list 变成 set,再用交集并集运算


import json
from typing import List, Dict, Any, Tuple

def compare_json_lists(list1: List[Dict], list2: List[Dict], key_field: str = None) -> Tuple[List[Dict], List[Dict], List[Dict]]:
    """
    比较两个JSON列表的差异
    
    参数:
        list1: 第一个JSON列表
        list2: 第二个JSON列表  
        key_field: 用于识别相同记录的关键字段名,如果为None则比较整个字典
    
    返回:
        Tuple(added, removed, modified)
        added: 在list2中存在但list1中不存在的记录
        removed: 在list1中存在但list2中不存在的记录
        modified: 在两个列表中都存在但有差异的记录
    """
    
    def create_lookup_dict(lst: List[Dict], key_field: str) -> Dict:
        """创建查找字典,key_field为None时使用整个字典作为key"""
        if key_field:
            return {item[key_field]: item for item in lst}
        else:
            # 使用json序列化后的字符串作为key,确保可哈希
            return {json.dumps(item, sort_keys=True): item for item in lst}
    
    # 创建查找字典
    dict1 = create_lookup_dict(list1, key_field)
    dict2 = create_lookup_dict(list2, key_field)
    
    if key_field:
        # 使用关键字段比较
        keys1 = set(dict1.keys())
        keys2 = set(dict2.keys())
        
        added = [dict2[key] for key in keys2 - keys1]
        removed = [dict1[key] for key in keys1 - keys2]
        
        # 找出修改的记录
        common_keys = keys1 & keys2
        modified = []
        for key in common_keys:
            if dict1[key] != dict2[key]:
                modified.append({
                    'old': dict1[key],
                    'new': dict2[key],
                    'key': key
                })
    else:
        # 直接比较整个字典
        set1 = set(dict1.keys())
        set2 = set(dict2.keys())
        
        added = [dict2[key] for key in set2 - set1]
        removed = [dict1[key] for key in set1 - set2]
        modified = []  # 当比较整个字典时,要么完全相同要么完全不同
    
    return added, removed, modified

# 使用示例
if __name__ == "__main__":
    # 示例数据
    old_data = [
        {"id": 1, "name": "Alice", "age": 25},
        {"id": 2, "name": "Bob", "age": 30},
        {"id": 3, "name": "Charlie", "age": 35}
    ]
    
    new_data = [
        {"id": 1, "name": "Alice", "age": 26},  # 年龄修改
        {"id": 2, "name": "Bob", "age": 30},    # 未变
        {"id": 4, "name": "David", "age": 28}   # 新增
    ]
    
    # 使用id作为关键字段进行比较
    added, removed, modified = compare_json_lists(old_data, new_data, key_field="id")
    
    print("新增的记录:", json.dumps(added, indent=2))
    print("\n删除的记录:", json.dumps(removed, indent=2))
    print("\n修改的记录:", json.dumps(modified, indent=2))
    
    # 也可以不使用关键字段,直接比较整个对象
    print("\n--- 不使用关键字段比较 ---")
    added2, removed2, modified2 = compare_json_lists(old_data, new_data)
    print(f"新增: {len(added2)} 条, 删除: {len(removed2)} 条")

这个方案的核心思路是通过关键字段建立查找字典,用集合操作快速找出差异。如果数据有唯一标识字段(如id),用key_field参数指定;如果没有,就序列化整个字典作为key来比较。返回结果清晰分为新增、删除、修改三部分,修改的记录还会包含新旧值对比。

简单说就是:用字典查找+集合运算,比逐条遍历快得多。

list 中可能存在重复元素,这些元素个数也需要一致。。

先转成字符串再对比?

用 collections.Counter([iterable-or-mapping]) 做做看呢?

那你可以包一个 python 对象再放进 set 里面,这个 python 对象指出 json 在原 list 里面的 index,这样他们的 hash 不一样,甚至你还可以自己再重载一下 hash

把 json load 出来 sort 比较?
我记得有专门比较 json 的库的,GitHub 上面应该能找到。

dictdiffer 可以试试

这个库好👍

感觉就是遍历啊,你用啥都绕不开这个的,只是用起来简便一点而已。

排序一下,格式化成字符串,然后用自带的 diff 库比较,这个库比对差异效率非常高。

谢谢,我待会儿试一下

for x,y in zip(list1,list2):
if x == y:
print(1)
else:
print(0)
#小白表示这样不行吗

原来 V2EX 没法显示缩进

两个 list 顺序可能不一样

回到顶部