繁体   English   中英

如何比较两个 json 对象以检查发生了什么变化?

[英]How to compare two json objects to check what has changed?

我有两个 json 对象如下:

json.json

{
    "access_points": [
        {
            "ssid": "MyAP",
            "snr": 63,
            "channel": 11
        },
        {
            "ssid": "YourAP",
            "snr": 42,
            "channel": 1
        },
        {
            "ssid": "HisAP",
            "snr": 54,
            "channel": 6
        }
    ]
}

json_.json

{
    "access_points": [
        {
            "ssid": "MyAP",
            "snr": 82,
            "channel": 11
        },
        {
            "ssid": "YourAP",
            "snr": 42,
            "channel": 6
        },
        {
            "ssid": "HerAP",
            "snr": 71,
            "channel": 1
        }
    ]
}

正如您在上面看到的,这些值发生了一些变化,如下所示:

  1. MyAP 的 SNR 从 63 变为 82
  2. YourAP 的频道已从 1 更改为 6
  3. HisAP 已从列表中删除
  4. HerAP 添加到 SNR 71 和频道 1 的列表中

我需要跟踪以上内容,我预期的 output 应该是:

Following items have changed: ==========================


1. MyAP’s SNR has changed from 63 to 82
2. YourAP’s channel has changed from 1 to 6
3. HisAP is removed from the list
4. HerAP is added to the list with SNR 71 and channel 1
========================================================

这就是我一直在尝试比较键的内容,但我对如何比较每个嵌套值感到困惑:

def checkIfEquals(obj):
    if isinstance(obj, dict):
        return sorted((k, checkIfEquals(v)) for k, v in obj.items())
    if isinstance(obj, list):
        return sorted(checkIfEquals(x) for x in obj)
    else:
        return obj

def test():

    # JSON string
    with open('/Users/jananath/Desktop/Int/tmp/json.json') as data_file:   
        one = json.load(data_file)
    
    with open('/Users/jananath/Desktop/Int/tmp/json_.json') as data_file:   
        two = json.load(data_file)
    

    areTheytheSame = checkIfEquals(one) == checkIfEquals(two)

    if areTheytheSame:
        print("Same")
    else:
        for key in two.keys():
            value = two[key] 
            if key not in one:
                print("found new key {0} with value {1}".format(key, value))
            else:
            #check if values are not same
                if one[key] != value: print("for key %s values are different" % key)

有人可以帮忙吗?

我的代码仅适用于您在示例数据中显示的结构。

至于我checkIfEquals是无用的,因为它不会创建我可以用来获取详细差异的结构。 为此,它仍然需要使用原始数据。 这样我就可以简单地在开始时设置the_same = True并逐个比较元素,当有差异时显示它并设置the_same = True 如果最后我有the_same = False那么我可以打印The same

但是何时将access_points作为字典获取很简单

one: {'MyAP': {'snr': 63, 'channel': 11}, 'YourAP': {'snr': 42, 'channel': 1}, 'HisAP': {'snr': 54, 'channel': 6}}
two: {'MyAP': {'snr': 82, 'channel': 11}, 'YourAP': {'snr': 42, 'channel': 6}, 'HerAP': {'snr': 71, 'channel': 1}}

因为现在我可以获得所有密钥( ssid )并转换为set()并检查添加了哪些,删除了哪些以及两者都包含了哪些。

one_keys = set(one.keys())
two_keys = set(two.keys())

only_one = sorted(one_keys - two_keys)
only_two = sorted(two_keys - one_keys)
both     = sorted(one_keys & two_keys)

稍后我可以使用only_one来显示删除的项目, only_two来显示添加的项目,并且both来比较snrchannel和显示差异。


完整的工作代码:

one = {
    "access_points": [
        {
            "ssid": "MyAP",
            "snr": 63,
            "channel": 11
        },
        {
            "ssid": "YourAP",
            "snr": 42,
            "channel": 1
        },
        {
            "ssid": "HisAP",
            "snr": 54,
            "channel": 6
        }
    ]
}

two = {
    "access_points": [
        {
            "ssid": "MyAP",
            "snr": 82,
            "channel": 11
        },
        {
            "ssid": "YourAP",
            "snr": 42,
            "channel": 6
        },
        {
            "ssid": "HerAP",
            "snr": 71,
            "channel": 1
        }
    ]
}

# --- functions ---

def get_access_points(data):
    result = {}
    for item in data["access_points"]:
        name = item['ssid']
        item.pop('ssid')
        result[name] = item
    return result

# --- main ---
    
one = get_access_points(one)
two = get_access_points(two)
print('one:', one)
print('two:', two)
print('---')

one_keys = set(one.keys())
two_keys = set(two.keys())

only_one = sorted(one_keys - two_keys)
only_two = sorted(two_keys - one_keys)
both = sorted(one_keys & two_keys)
print('only_one:', only_one)
print('only_two:', only_two)
print('both    :', both)
print('---')

the_same = True

for key in both:
    item1 = one[key]
    item2 = two[key]
    if item1["snr"] != item2["snr"]:
        print(f'{key:10} | changed | SNR from {item1["snr"]} to {item2["snr"]}')
        the_same = False
    if item1["channel"] != item2["channel"]:
        print(f'{key:10} | changed | CHANNEL from {item1["channel"]} to {item2["channel"]}')
        the_same = False

for key in only_one:
    item = one[key]    
    print(f'{key:10} | removed | with SNR {item["snr"]} and CHANNEL {item["channel"]}')
    the_same = False    

for key in only_two:
    item = two[key]
    print(f'{key:10} | added   | with SNR {item["snr"]} and CHANNEL {item["channel"]}')
    the_same = False    

if the_same:
    print('The same')

结果:

one: {'MyAP': {'snr': 63, 'channel': 11}, 'YourAP': {'snr': 42, 'channel': 1}, 'HisAP': {'snr': 54, 'channel': 6}}
two: {'MyAP': {'snr': 82, 'channel': 11}, 'YourAP': {'snr': 42, 'channel': 6}, 'HerAP': {'snr': 71, 'channel': 1}}
---
only_one: ['HisAP']
only_two: ['HerAP']
both    : ['MyAP', 'YourAP']
---
MyAP       | changed | SNR from 63 to 82
YourAP     | changed | CHANNEL from 1 to 6
HisAP      | removed | with SNR 54 and CHANNEL 6
HerAP      | added   | with SNR 71 and CHANNEL 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM