Skip to content

How to Compare JSON Objects Regardless of Order in Python

Learn how to compare JSON objects in Python while ignoring key or array element order, including recursive deep comparison for nested structures and handling edge cases like mixed data types.

JSON (JavaScript Object Notation) is the most widely used data interchange format in modern web applications and APIs. When working with JSON data in Python, you'll frequently need to compare two JSON objects to check if they contain the same data, even when the keys or array elements appear in a different order.

This is a common challenge because JSON object properties have no guaranteed order, and two API responses with identical data might serialize keys differently. In this guide, you'll learn multiple reliable methods to compare JSON objects regardless of order in Python, handling everything from simple flat structures to deeply nested objects.

The Problem: Order Shouldn't Matter

Consider two JSON strings that represent the same data but with different key ordering:

import json

json_1 = '{"name": "Alice", "age": 30, "city": "London"}'
json_2 = '{"city": "London", "name": "Alice", "age": 30}'

A simple string comparison would fail even though the data is identical:

print(json_1 == json_2)

Output:

False

The strings are different, but the data they represent is the same. We need smarter comparison methods.

Comparing Simple JSON Objects Directly

For flat JSON objects (no nested structures or arrays), you can parse them into Python dictionaries and compare directly. Python dictionaries compare by content, not by insertion order.

import json

json_1 = '{"name": "Alice", "age": 30, "city": "London"}'
json_2 = '{"city": "London", "name": "Alice", "age": 30}'

dict_1 = json.loads(json_1)
dict_2 = json.loads(json_2)

print(dict_1 == dict_2)

Output:

True

Using sorted() for Top-Level Comparison

You can also sort dictionary items and compare them. This approach makes the comparison explicit:

import json

json_1 = '{"name": "Alice", "age": 30, "city": "London"}'
json_2 = '{"city": "London", "name": "Alice", "age": 30}'

dict_1 = json.loads(json_1)
dict_2 = json.loads(json_2)

print(sorted(dict_1.items()) == sorted(dict_2.items()))

Output:

True

For robust comparison of complex JSON objects, including nested dictionaries and arrays in any order, use a recursive sorting function that normalizes the entire structure before comparing.

import json

def normalize(obj):
    """Recursively sort dictionaries and lists for order-independent comparison."""
    if isinstance(obj, dict):
        return sorted((k, normalize(v)) for k, v in obj.items())
    if isinstance(obj, list):
        return sorted(normalize(item) for item in obj)
    return obj


json_1 = '{"name": "Alice", "skills": ["Python", "Java", "SQL"], "address": {"city": "London", "country": "UK"}}'
json_2 = '{"address": {"country": "UK", "city": "London"}, "skills": ["SQL", "Python", "Java"], "name": "Alice"}'

dict_1 = json.loads(json_1)
dict_2 = json.loads(json_2)

print(normalize(dict_1) == normalize(dict_2))

Output:

True

How it works:

  1. Dictionaries are converted into sorted lists of (key, value) tuples, ensuring key order doesn't affect comparison.
  2. Lists are sorted so element order doesn't matter.
  3. Primitive values (strings, numbers, booleans, None) are returned as-is.
  4. The function calls itself recursively, handling any depth of nesting.

Testing with Complex Nested JSON

import json

def normalize(obj):
    """Recursively sort dictionaries and lists for order-independent comparison."""
    if isinstance(obj, dict):
        return sorted((k, normalize(v)) for k, v in obj.items())
    if isinstance(obj, list):
        return sorted(normalize(item) for item in obj)
    return obj

json_1 = '''
{
    "company": "TechCorp",
    "employees": [
        {"name": "Bob", "skills": ["Java", "Python"]},
        {"name": "Alice", "skills": ["SQL", "Python"]}
    ],
    "locations": ["London", "New York", "Tokyo"]
}
'''

json_2 = '''
{
    "locations": ["Tokyo", "London", "New York"],
    "company": "TechCorp",
    "employees": [
        {"skills": ["Python", "SQL"], "name": "Alice"},
        {"skills": ["Python", "Java"], "name": "Bob"}
    ]
}
'''

dict_1 = json.loads(json_1)
dict_2 = json.loads(json_2)

print(f"Direct comparison:    {dict_1 == dict_2}")
print(f"Normalized comparison: {normalize(dict_1) == normalize(dict_2)}")

Output:

Direct comparison:    False
Normalized comparison: True

Using json.dumps() with sort_keys

A simpler alternative for many cases is to serialize both objects to JSON strings with sort_keys=True, then compare the strings:

import json

json_1 = '{"name": "Alice", "age": 30, "city": "London"}'
json_2 = '{"city": "London", "name": "Alice", "age": 30}'

dict_1 = json.loads(json_1)
dict_2 = json.loads(json_2)

normalized_1 = json.dumps(dict_1, sort_keys=True)
normalized_2 = json.dumps(dict_2, sort_keys=True)

print(normalized_1 == normalized_2)
print(normalized_1)

Output:

True
{"age": 30, "city": "London", "name": "Alice"}

This approach sorts dictionary keys at all nesting levels but does not sort array elements, which may be exactly what you want if list order is significant.

import json

dict_1 = {"b": 2, "a": {"d": 4, "c": 3}}
dict_2 = {"a": {"c": 3, "d": 4}, "b": 2}

print(json.dumps(dict_1, sort_keys=True) == json.dumps(dict_2, sort_keys=True))

Output:

True

Using deepdiff for Detailed Comparison

For production applications where you need to know what's different (not just whether objects are equal), the third-party deepdiff library provides comprehensive comparison with detailed reports.

pip install deepdiff
from deepdiff import DeepDiff

dict_1 = {
    "name": "Alice",
    "age": 30,
    "skills": ["Python", "Java"]
}

dict_2 = {
    "name": "Alice",
    "age": 31,
    "skills": ["Java", "Python", "SQL"]
}

diff = DeepDiff(dict_1, dict_2, ignore_order=True)

if diff:
    print("Differences found:")
    for diff_type, details in diff.items():
        print(f"  {diff_type}: {details}")
else:
    print("Objects are identical.")

Output:

Differences found:
  values_changed: {"root['age']": {'new_value': 31, 'old_value': 30}}
  iterable_item_added: {"root['skills'][2]": 'SQL'}

Building a Reusable Comparison Function

Here's a complete, reusable function that handles various comparison scenarios:

import json

def compare_json(json_1, json_2, ignore_list_order=True):
    """
    Compare two JSON objects for equality regardless of key order.
    
    Args:
        json_1: JSON string or Python dict/list.
        json_2: JSON string or Python dict/list.
        ignore_list_order: If True, list element order is ignored.
    
    Returns:
        True if objects are equal, False otherwise.
    """
    if isinstance(json_1, str):
        json_1 = json.loads(json_1)
    if isinstance(json_2, str):
        json_2 = json.loads(json_2)

    def normalize(obj):
        if isinstance(obj, dict):
            return sorted((k, normalize(v)) for k, v in obj.items())
        if isinstance(obj, list):
            if ignore_list_order:
                return sorted(normalize(item) for item in obj)
            return [normalize(item) for item in obj]
        return obj

    return normalize(json_1) == normalize(json_2)


print(compare_json('{"a": 1, "b": 2}', '{"b": 2, "a": 1}'))
print(compare_json('{"x": [3, 1, 2]}', '{"x": [1, 2, 3]}'))
print(compare_json('{"x": [3, 1, 2]}', '{"x": [1, 2, 3]}', ignore_list_order=False))

Output:

True
True
False

Quick Comparison of Methods

Method Handles Nested Dicts Handles List Order Shows Differences External Dependency
Direct == comparison ✅ ❌ (order matters) ❌ None
sorted() on items ❌ (top-level only) ❌ ❌ None
Recursive normalize() ✅ ✅ (configurable) ❌ None
json.dumps(sort_keys=True) ✅ (keys only) ❌ (order matters) ❌ None
deepdiff ✅ ✅ ✅ deepdiff

Conclusion

Comparing JSON objects regardless of order in Python requires different approaches depending on the complexity of your data:

  • For flat JSON objects, direct dictionary comparison (dict_1 == dict_2) works out of the box since Python dicts are order-independent.
  • For nested objects with ordered lists, use json.dumps(sort_keys=True) to normalize key order at all levels.
  • For full order-independent comparison (including arrays), use a recursive normalization function that sorts both dictionaries and lists before comparing.
  • For detailed difference reports, use the deepdiff library with ignore_order=True to see exactly what differs between two JSON objects.

The recursive normalize() approach is the most versatile pure-Python solution and handles the vast majority of real-world comparison scenarios.

Navigation