JSON key order does not matter to the meaning of the data. The JSON spec defines an object as unordered, so {"a": 1, "b": 2} and {"b": 2, "a": 1} are the same object. Key order does matter in four practical places: hashes and signatures, text diffs, code that reads keys by position, and storage that quietly rewrites the order.
What the JSON spec says about key order
The JSON spec says object key order carries no meaning. RFC 8259 defines an object as "an unordered collection of zero or more name/value pairs". Two objects with the same pairs hold the same data, whatever order the keys were written in.
The same RFC also admits that real software is less tidy. It notes that "JSON parsing libraries have been observed to differ as to whether or not they make the ordering of object members visible to calling software." Some parsers hand you keys in file order, some don't, and the spec doesn't pick a side.
Arrays are a different story. An array is an ordered list, so [1, 2] and [2, 1] are different values. If the order of items means something, it belongs in an array, not in object keys.
How common parsers handle JSON key order
Each language and database makes its own choice about key order, and that choice is where surprises come from.
| Parser or store | What happens to key order |
|---|---|
JavaScript (JSON.parse, objects) |
Integer-like keys move to the front in ascending order; other keys keep creation order |
Python json |
Input and output order are preserved by default |
Go encoding/json v1 |
Maps are marshaled in a deterministic order |
Go encoding/json v2 |
Maps are marshaled in a non-deterministic order |
PostgreSQL json |
Exact copy of the input text, key order kept |
PostgreSQL jsonb |
Key order is not preserved |
JavaScript moves integer-like keys first
JavaScript keeps insertion order for most keys but sorts integer-like keys ahead of them. MDN's for...in reference says all non-negative integer keys are traversed first in ascending order, then other string keys in the order they were created. The rule is well defined and the same across engines.
The Object.keys() page shows it with { 100: "a", 2: "b", 7: "c" }, which comes back as ['2', '7', '100']. So a response keyed by product ID, like {"100": ..., "2": ..., "7": ...}, is reordered the moment JSON.parse reads it.
JSON.stringify visits properties with the same algorithm as Object.keys(). That means a parse-and-stringify round trip keeps the object's own order, but it can't restore the original file order once the integer-like keys have moved. Any formatter built on those two calls behaves the same way.
Python keeps the order you gave it
Python's json module keeps key order unless you ask it not to. The Python json documentation says the module's "encoders and decoders preserve input and output order by default", and order is only lost if the underlying containers are unordered.
To get a stable order instead, pass sort_keys=True to json.dumps. The docs describe it as useful for regression tests, so that serializations can be compared day to day.
import json
data = {"b": 2, "a": 1}
print(json.dumps(data)) # {"b": 2, "a": 1}
print(json.dumps(data, sort_keys=True)) # {"a": 1, "b": 2}
Go maps depend on the encoder version
Go's answer for maps depends on which version of the package you use. The encoding/json package docs state that in v1 "a Go map is marshaled in a deterministic order", while in v2 "a Go map is marshaled in a non-deterministic order."
Code that hashes or diffs Go output from maps shouldn't assume the order stays the same after an upgrade to v2.
PostgreSQL jsonb rewrites the order
PostgreSQL has two JSON column types, and only one of them keeps your key order. According to the PostgreSQL JSON types documentation, the json type stores an exact copy of the input text, including key order. By contrast, "jsonb does not preserve white space, does not preserve the order of object keys, and does not keep duplicate object keys."
People insert a config object, read it back, and see the keys shuffled. The data is fine. The column type just doesn't store order.
When JSON key order does matter
Key order matters whenever something compares the JSON as text or bytes instead of as data.
- Hashes and signatures. A hash covers bytes, so reordered keys give a different hash for the same data.
- Text diffs and Git. A line diff reports moved keys as changes. Our guide to comparing JSON while ignoring key order shows how to normalize first.
- Code that reads by position. Taking "the first key" of an object is a bug waiting for the next parser or database to change the order.
- Human readability. Putting
idandnamefirst makes a payload easier to scan, even though no parser needs it.
Sorting keys for hashes and signatures
Canonical JSON is the fix when two systems must produce identical bytes. RFC 8785, the JSON Canonicalization Scheme, explains why: "Cryptographic operations like hashing and signing need the data to be expressed in an invariant format so that the operations are reliably repeatable."
Object properties must be sorted recursively, so nested objects are sorted too, while array element order must not change. Names are compared as UTF-16 code units, independent of locale. RFC 8785 is informational, not Standards Track, so check that both sides of your system use the same implementation.
My take: if a value gets hashed or signed, canonicalize it every time, even if today's serializer happens to give stable output. Plain sort_keys=True is fine for diffs and tests, but number formatting and whitespace also change the bytes, and RFC 8785 pins those down as well.
Duplicate keys make order matter again
Duplicate keys are the one case where order changes which value you get. RFC 8259 says names "SHOULD be unique", and when they aren't, behavior is unpredictable; "Many implementations report the last name/value pair only."
Python's json module ignores all but the last pair for a repeated name, and PostgreSQL jsonb keeps only the last value. So in {"mode": "test", "mode": "live"}, swapping the two keys flips the result. Because the RFC only says "SHOULD", a syntax check such as a JSON validator is not the place to catch this, so search for repeated names by hand when a value looks wrong.
If key order carries meaning, use an array
When order is part of your data, put it in an array. Object keys are the wrong tool, because any parser or database along the way is allowed to reorder them.
{
"steps": [
{"name": "build"},
{"name": "test"},
{"name": "deploy"}
]
}
The limitation is size and readability: an array of objects is wordier than a keyed object, and lookups by name need a loop or an index. Pay it anyway when order is a requirement. For a refresher on the basic types, see what JSON format is, and for another way parsers quietly change data, read about JSON.parse and large number precision.
FAQ
Is JSON key order guaranteed?
No. RFC 8259 defines an object as an unordered collection of name/value pairs, and it notes that parsing libraries differ on whether they expose member order at all.
Does JSON.stringify keep key order?
Mostly. It visits properties in the same order as Object.keys(): integer-like keys first in ascending order, then other keys in the order they were created.
Does PostgreSQL keep JSON key order?
The json type keeps an exact copy of the input, including key order. The jsonb type does not preserve the order of object keys.
Does array order matter in JSON?
Yes. Only objects are unordered. Canonical forms such as RFC 8785 sort object keys but must not change array element order.
How do I get the same key order every time?
Sort keys when you serialize, for example with sort_keys=True in Python, or canonicalize with RFC 8785 before hashing or signing.