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
Answer from Zero Piraeus on Stack OverflowIf 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
Another way could be to use json.dumps(X, sort_keys=True) option:
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.
Python - Compare two JSON with different length and without order - Stack Overflow
python - Comparing two JSON objects irrespective of the sequence of elements in them - Stack Overflow
How to compare two json objects ignoring the order of fields
Comparing JSON Files While Excluding Certain Keys
Videos
You can use jsondiff
from jsondiff import diff
diff(json1, json2)
... assuming you have json1 and json2 loaded with the json entries from your example (and by the way, you have a missing comma after the 'sex' entry).
you can use deepdiff with ignore_order=True
from deepdiff import DeepDiff
t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
ddiff = DeepDiff(t1, t2, ignore_order=True)
print (ddiff)
{}
Hi everyone,
We have two JSON files we could like to compare. Problem is, some values are different (like current time and date for example), and we want to exclude those values. There couple of solution I can think about:
-
Ignore the fact it's a JSON and MASK specific data. So the original file will look like `"time": "1/1/2019"` for example. I will looking for the file using REGEX for `"time"` and change the value to `*MASKED*`. The file I compare to will already have this, so diff will pass successfully. I'm not a fan of this - because Regex and manual masking can get very complex really fast.
-
I can just turn the JSON into Dict, and remove the keys. This way I can compare only the relevant data.
-
A third option will be looking for a Python library that does something like that already (I couldn't find myself) that diff json files but allow excludes. Or write my class that compare Dicts and ignore specific keys if they showing up. But this again can get very complex early one with nested Dicts (JSON).
Any ideas?
Lodash _.isEqual allows you to do that:
var
remoteJSON = {"allowExternalMembers": "false", "whoCanJoin": "CAN_REQUEST_TO_JOIN"},
localJSON = {"whoCanJoin": "CAN_REQUEST_TO_JOIN", "allowExternalMembers": "false"};
console.log( _.isEqual(remoteJSON, localJSON) );
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Lodash isEqual() method is the best way to compare two JSON object.
This will not consider the order of the keys in object and check for the equality of object. Example
const object1 = {
name: 'ABC',
address: 'India'
};
const object2 = {
address: 'India',
name: 'ABC'
};
JSON.stringify(object1) === JSON.stringify(object2)
// false
_.isEqual(object1, object2)
// true
Reference - https://lodash.com/docs/#isEqual
If sequence is not going to change than JSON.stringify() will be fast as compared to Lodash's isEqual() method.
Reference - https://www.measurethat.net/Benchmarks/Show/1854/0/lodash-isequal-test