json
python
json.dumps
data ordering
serialization

Items in JSON object are out of order using json.dumps?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Python 3.6 and earlier, json.dumps() did not preserve dictionary insertion order because dict was unordered. Starting with Python 3.7, dict officially maintains insertion order, and json.dumps() outputs keys in insertion order by default. If you need alphabetical key ordering, use json.dumps(data, sort_keys=True). If you are seeing unexpected order, it is because the dictionary was constructed in a different order than you expected, or you are using Python 3.6 or earlier.

Default Behavior (Python 3.7+)

python
1import json
2
3data = {"name": "Alice", "age": 30, "city": "NYC"}
4print(json.dumps(data))
5# {"name": "Alice", "age": 30, "city": "NYC"}
6# Keys appear in insertion order

Since Python 3.7, dict preserves insertion order as a language guarantee (it was an implementation detail in CPython 3.6). json.dumps() respects this order.

Sorting Keys Alphabetically

python
1import json
2
3data = {"name": "Alice", "age": 30, "city": "NYC"}
4
5print(json.dumps(data, sort_keys=True))
6# {"age": 30, "city": "NYC", "name": "Alice"}

sort_keys=True sorts all keys alphabetically at every nesting level. This is useful for deterministic output, diffing, and version control.

Why Order Might Seem Wrong

python
1import json
2
3# Loaded from a JSON string, order matches the source
4loaded = json.loads('{"z": 1, "a": 2, "m": 3}')
5print(json.dumps(loaded))
6# {"z": 1, "a": 2, "m": 3} (preserves source order)
7
8# Merged dictionaries, order depends on merge
9base = {"b": 1, "a": 2}
10extra = {"c": 3}
11merged = {**base, **extra}
12print(json.dumps(merged))
13# {"b": 1, "a": 2, "c": 3}
14
15# From a database query, order depends on column order
16import sqlite3
17conn = sqlite3.connect(":memory:")
18conn.row_factory = sqlite3.Row
19# Row order depends on SELECT column order

The JSON output order mirrors the dict insertion order. If the source data arrives in an unexpected order, the JSON reflects that.

OrderedDict (Pre-Python 3.7)

python
1from collections import OrderedDict
2import json
3
4# In Python 3.6 and earlier, use OrderedDict for guaranteed order
5data = OrderedDict([
6    ("name", "Alice"),
7    ("age", 30),
8    ("city", "NYC")
9])
10
11print(json.dumps(data))
12# {"name": "Alice", "age": 30, "city": "NYC"}

In Python 3.7+, regular dict provides the same ordering guarantee, making OrderedDict unnecessary for this purpose.

Parsing JSON with Preserved Order

python
1import json
2from collections import OrderedDict
3
4json_string = '{"z": 1, "a": 2, "m": 3}'
5
6# Default: preserves order (Python 3.7+)
7data = json.loads(json_string)
8print(list(data.keys()))  # ['z', 'a', 'm']
9
10# Explicit OrderedDict (useful for Python 3.6 or for equality comparison)
11data = json.loads(json_string, object_pairs_hook=OrderedDict)
12print(list(data.keys()))  # ['z', 'a', 'm']

Custom Key Order

python
1import json
2
3data = {"status": "active", "id": 42, "name": "Alice", "email": "[email protected]"}
4
5# Define your preferred key order
6key_order = ["id", "name", "email", "status"]
7
8ordered = {k: data[k] for k in key_order if k in data}
9print(json.dumps(ordered, indent=2))
10# {
11#   "id": 42,
12#   "name": "Alice",
13#   "email": "[email protected]",
14#   "status": "active"
15# }

Pretty Printing with Order

python
1import json
2
3data = {"name": "Alice", "age": 30, "address": {"city": "NYC", "zip": "10001"}}
4
5# Indented, insertion order
6print(json.dumps(data, indent=2))
7# {
8#   "name": "Alice",
9#   "age": 30,
10#   "address": {
11#     "city": "NYC",
12#     "zip": "10001"
13#   }
14# }
15
16# Indented, sorted keys
17print(json.dumps(data, indent=2, sort_keys=True))
18# {
19#   "address": {
20#     "city": "NYC",
21#     "zip": "10001"
22#   },
23#   "age": 30,
24#   "name": "Alice"
25# }

Deterministic JSON for Hashing or Comparison

python
1import json
2import hashlib
3
4def canonical_json(data):
5    """Produce deterministic JSON output for hashing."""
6    return json.dumps(data, sort_keys=True, separators=(',', ':'))
7
8# Same data, different insertion order
9a = {"x": 1, "y": 2}
10b = {"y": 2, "x": 1}
11
12print(canonical_json(a))  # {"x":1,"y":2}
13print(canonical_json(b))  # {"x":1,"y":2}
14
15# Same canonical form → same hash
16hash_a = hashlib.sha256(canonical_json(a).encode()).hexdigest()
17hash_b = hashlib.sha256(canonical_json(b).encode()).hexdigest()
18print(hash_a == hash_b)  # True

separators=(',', ':') removes extra whitespace for minimal, deterministic output.

JSON Spec and Key Order

The JSON specification (RFC 8259) states:

An object is an unordered collection of zero or more name/value pairs.

This means:

  • JSON parsers are not required to preserve key order
  • {"a":1,"b":2} and {"b":2,"a":1} are semantically equal
  • Applications should not depend on key order in JSON

Python's json module preserves order as a convenience, but other languages and tools may not.

Common Pitfalls

  • Expecting alphabetical order by default: json.dumps() uses insertion order, not alphabetical. Use sort_keys=True if you need alphabetical.
  • Comparing JSON strings directly: '{"a":1,"b":2}' != '{"b":2,"a":1}' as strings, but they are equivalent JSON. Use json.loads() and compare dictionaries, or use sort_keys=True for canonical form.
  • Assuming all parsers preserve order: JavaScript's JSON.parse() preserves order in modern engines, but the spec does not guarantee it. Databases, APIs, and older parsers may reorder keys.
  • Nested ordering: sort_keys=True sorts keys at all levels. If you need sorting only at the top level, you must build the ordered dict manually and use sort_keys=False.
  • Performance of sort_keys: Sorting adds O(k log k) overhead per object (k = number of keys). For very large JSON with thousands of keys per object, this can be measurable.

Summary

  • Python 3.7+ dict preserves insertion order, and json.dumps() respects it
  • Use sort_keys=True for alphabetical ordering at all nesting levels
  • Use separators=(',', ':') with sort_keys=True for deterministic canonical JSON
  • The JSON spec says objects are unordered, so do not depend on key order across systems
  • For custom key order, build an ordered dict with a comprehension before serializing
  • Compare JSON by parsing to dicts, not by comparing strings

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.