且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何比较两个JSON对象与相同的元素在不同的顺序相等?

更新时间:2022-10-14 19:55:12

如果你想要两个对象具有相同的元素,但以不同的顺序来比较相等,那么显而易见的做法是比较它们的排序副本 - 例如,您的JSON字符串 a b 表示的字典:

  import json 

a = json.loads(
{
errors:[
{错误:invalid,field:email},
{error:required,field:name}
],
success false
}


b = json.loads(
{
success:false,
错误:[
{error:required,field:name},
{error:invalid,field:email}
]
}





 >>> sort(a.items())== sorted(b.items())
False

...但是这不工作,因为在每种情况下,顶层dict的errors项是一个列表,不同的顺序, sorted()不会尝试排序除了可迭代的***别之外的任何东西。



有序的函数,它将递归排序它找到的任何列表(并将字典转换为(key,value )对,以便它们是可订购的):
  def ordered(obj):
如果isinstance(obj,dict):
return obj.items()中的k,v的排序((k, b return sort(x(x)for obj)
else:
return obj


$ b b

如果我们将此函数应用于 a b ,结果会比较:

 >>> ordered(a)== ordered(b)
True


How can I test whether two JSON objects are equal in python, disregarding the order of lists?

For example ...

JSON document a:

{
    "errors": [
        {"error": "invalid", "field": "email"},
        {"error": "required", "field": "name"}
    ],
    "success": false
}

JSON document b:

{
    "success": false,
    "errors": [
        {"error": "required", "field": "name"},
        {"error": "invalid", "field": "email"}
    ]
}

a and b should compare equal, even though the order of the "errors" lists are different.

If you want two objects with the same elements but in a different order to compare equal, then the obvious thing to do is compare sorted copies of them - for instance, for the dictionaries represented by your JSON strings a and b:

import json

a = json.loads("""
{
    "errors": [
        {"error": "invalid", "field": "email"},
        {"error": "required", "field": "name"}
    ],
    "success": false
}
""")

b = json.loads("""
{
    "success": false,
    "errors": [
        {"error": "required", "field": "name"},
        {"error": "invalid", "field": "email"}
    ]
}
""")

>>> sorted(a.items()) == sorted(b.items())
False

... but that doesn't work, because in each case, the "errors" item of the top-level dict is a list with the same elements in a different order, and sorted() doesn't try to sort anything except the "top" level of an iterable.

To fix that, we can define an ordered function which will recursively sort any lists it finds (and convert dictionaries to lists of (key, value) pairs so that they're orderable):

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

If we apply this function to a and b, the results compare equal:

>>> ordered(a) == ordered(b)
True