How to Compare Two JSON Objects with the Same Elements in a Different Order Equal

How to compare two JSON objects with the same elements in a different order equal?

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

Testing two JSON objects for equality ignoring child order in Java

As a general architectural point, I usually advise against letting dependencies on a particular serialization format bleed out beyond your storage/networking layer; thus, I'd first recommend that you consider testing equality between your own application objects rather than their JSON manifestations.

Having said that, I'm currently a big fan of Jackson which my quick read of their ObjectNode.equals() implementation suggests does the set membership comparison that you want:

public boolean equals(Object o)
{
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != getClass()) {
return false;
}
ObjectNode other = (ObjectNode) o;
if (other.size() != size()) {
return false;
}
if (_children != null) {
for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
String key = en.getKey();
JsonNode value = en.getValue();

JsonNode otherValue = other.get(key);

if (otherValue == null || !otherValue.equals(value)) {
return false;
}
}
}
return true;
}

Python - Compare two JSON with different length and without order

I made the operation with three different loops. First I added 0 id items as new to Query.

I also made isUpdated=True so it won't count in the other loops because in other loops I will only count isUpdated=False attributed items.

for jsonItem in getJson:
if jsonItem['Id'] == 0:
newMeta = ProductMeta(user=selectedProduct, metaVal=jsonItem['Input'].title(
), metaKey=jsonItem['Label'].title(), isUpdated=True)
newMeta.full_clean()
newMeta.save()

I call my query that should be updated.

selectedProductForm = ProductMeta.objects.filter(
user=selectedProduct, isDeleted=False, isUpdated=False)

The overwrite method for update operation.

for form in selectedProductForm:
for jsonItem in getJson:
if form.id == jsonItem['Id'] and form.isUpdated == False:
if jsonItem['Label'] is not None and jsonItem['Label'][0:1].isalnum() == True:
form.metaKey = jsonItem['Label'].title()
else:
form.metaKey = form.metaKey
if jsonItem['Input'] is not None and jsonItem['Input'][0:1].isalnum() == True:
form.metaVal = jsonItem['Input'].title()
form.isUpdated = True
form.save()

So, there will be only deletable items left because all of added and overwrited items' isUpdate attribute are False.

for form in selectedProductForm:
if form.isUpdated == False:
form.isDeleted = True
form.isUpdated = True
form.save()

After all these operations I make isUpdated=false of all items in order to make update operation again later.

formRefresh = UserMeta.objects.filter(
user=selectedProduct).update(isUpdated=False)

Compare two JSON Files and Return the Difference

with open("file1.json", "r") as f1:
file1 = json.loads(f1.read())
with open("file2.json", "r") as f2:
file2 = json.loads(f2.read())

for item in file2:
if item not in file1:
print(f"Found difference: {item}")
file1.append(item)

print(f"New file1: {file1}")

I want to compare two json objects excluding one of the keys from it

Thanks everyone for quick responses on my question but below was an easy method from which I could implement the above logic

import omit from "lodash/omit";
import isEqual from "lodash/isEqual";

let x = {a: 5, b: 6, c: "string"},
y = {a: 5, b: 8, c: "string"}

result = isEqual(omit(x, ['c']), omit(y, ['c']))

How to compare two JSON strings when the order of entries keep changing

Jackson Json parser has a nice feature that it can parse a Json String into a Map. You can then query the entries or simply ask on equality:

import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.*;

public class Test
{
public static void main(String... args)
{
String input1 = "{\"state\":1,\"cmd\":1}";
String input2 = "{\"cmd\":1,\"state\":1}";
ObjectMapper om = new ObjectMapper();
try {
Map<String, Object> m1 = (Map<String, Object>)(om.readValue(input1, Map.class));
Map<String, Object> m2 = (Map<String, Object>)(om.readValue(input2, Map.class));
System.out.println(m1);
System.out.println(m2);
System.out.println(m1.equals(m2));
} catch (Exception e) {
e.printStackTrace();
}
}
}

The output is

{state=1, cmd=1}
{cmd=1, state=1}
true


Related Topics



Leave a reply



Submit