How can I test whether two JSON objects are equal in python, disregarding the order of lists?
如何测试两个JSON对象在python中是否相等,而不考虑列表的顺序?
For example ...
例如……
JSON document a:
JSON文档:
{
"errors": [
{"error": "invalid", "field": "email"},
{"error": "required", "field": "name"}
],
"success": false
}
JSON document b:
JSON文档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.
a和b应该比较相等,即使“错误”列表的顺序不同。
3 个解决方案
#1
72
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
:
如果您希望两个对象具有相同的元素,但以不同的顺序进行比较,那么显然要做的事情是比较它们的已排序副本——例如,对于由JSON字符串a和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.
…但这是行不通的,因为在每种情况下,*词典的“error”项都是一个具有相同元素的列表,其顺序不同,sort()除了可迭代的“top”级别之外,不尝试对任何内容进行排序。
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):
为了解决这个问题,我们可以定义一个有序函数,它将对它找到的任何列表进行递归排序(并将字典转换为(key, value)对的列表,以便它们是有序的):
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:
如果我们把这个函数应用于a和b,结果是相等的:
>>> ordered(a) == ordered(b)
True
#2
15
Another way could be to use json.dumps(X, sort_keys=True)
option:
另一种方法是使用json。转储(X,sort_keys = True)选择:
import json
a, b = json.dumps(a, sort_keys=True), json.dumps(b, sort_keys=True)
a == b # a normal string comparison
This works for nested dictionaries and lists.
这适用于嵌套字典和列表。
#3
11
Decode them and compare them as mgilson comment.
对它们进行解码,并将其与mgilson的评论进行比较。
Order does not matter for dictionary as long as the keys, and values matches. (Dictionary has no order in Python)
只要键和值匹配,字典的顺序就不重要。(Python中字典没有顺序)
>>> {'a': 1, 'b': 2} == {'b': 2, 'a': 1}
True
But order is important in list; sorting will solve the problem for the lists.
但是顺序在列表中很重要;排序将解决列表的问题。
>>> [1, 2] == [2, 1]
False
>>> [1, 2] == sorted([2, 1])
True
>>> a = '{"errors": [{"error": "invalid", "field": "email"}, {"error": "required", "field": "name"}], "success": false}'
>>> b = '{"errors": [{"error": "required", "field": "name"}, {"error": "invalid", "field": "email"}], "success": false}'
>>> a, b = json.loads(a), json.loads(b)
>>> a['errors'].sort()
>>> b['errors'].sort()
>>> a == b
True
Above example will work for the JSON in the question. For general solution, see Zero Piraeus's answer.
上面的示例将适用于问题中的JSON。对于一般解,请参见零比雷埃夫斯的答案。
#1
72
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
:
如果您希望两个对象具有相同的元素,但以不同的顺序进行比较,那么显然要做的事情是比较它们的已排序副本——例如,对于由JSON字符串a和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.
…但这是行不通的,因为在每种情况下,*词典的“error”项都是一个具有相同元素的列表,其顺序不同,sort()除了可迭代的“top”级别之外,不尝试对任何内容进行排序。
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):
为了解决这个问题,我们可以定义一个有序函数,它将对它找到的任何列表进行递归排序(并将字典转换为(key, value)对的列表,以便它们是有序的):
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:
如果我们把这个函数应用于a和b,结果是相等的:
>>> ordered(a) == ordered(b)
True
#2
15
Another way could be to use json.dumps(X, sort_keys=True)
option:
另一种方法是使用json。转储(X,sort_keys = True)选择:
import json
a, b = json.dumps(a, sort_keys=True), json.dumps(b, sort_keys=True)
a == b # a normal string comparison
This works for nested dictionaries and lists.
这适用于嵌套字典和列表。
#3
11
Decode them and compare them as mgilson comment.
对它们进行解码,并将其与mgilson的评论进行比较。
Order does not matter for dictionary as long as the keys, and values matches. (Dictionary has no order in Python)
只要键和值匹配,字典的顺序就不重要。(Python中字典没有顺序)
>>> {'a': 1, 'b': 2} == {'b': 2, 'a': 1}
True
But order is important in list; sorting will solve the problem for the lists.
但是顺序在列表中很重要;排序将解决列表的问题。
>>> [1, 2] == [2, 1]
False
>>> [1, 2] == sorted([2, 1])
True
>>> a = '{"errors": [{"error": "invalid", "field": "email"}, {"error": "required", "field": "name"}], "success": false}'
>>> b = '{"errors": [{"error": "required", "field": "name"}, {"error": "invalid", "field": "email"}], "success": false}'
>>> a, b = json.loads(a), json.loads(b)
>>> a['errors'].sort()
>>> b['errors'].sort()
>>> a == b
True
Above example will work for the JSON in the question. For general solution, see Zero Piraeus's answer.
上面的示例将适用于问题中的JSON。对于一般解,请参见零比雷埃夫斯的答案。