About JSON Sort Keys
Sorting keys rewrites a JSON document with every object's properties in alphabetical order, recursively. The data is unchanged - JSON objects are unordered by specification - but the text becomes canonical, and that is what makes it useful.
The main reason to do it is diffing. Two serialisers, two language runtimes, or two versions of the same service will happily emit the same data with keys in different orders, and a line-based diff then reports the whole document as changed. Sorting both sides first reduces the diff to actual differences.
It is equally useful for anything that hashes or signs a document. If you compute a checksum, cache key or signature over serialised JSON, key order must be deterministic or the same data produces different results. Sorting is the simplest canonicalisation; if you need a rigorous one, JSON Canonicalization Scheme (RFC 8785) also pins number formatting and string escaping.
Be aware that most parsers do preserve insertion order in practice even though the specification does not require it, so a few systems have come to depend on the order they receive. Sorting is safe for the overwhelming majority of consumers, but it is a text change, and it is worth knowing whether anything downstream reads the first key of an object as meaningful.
Sorting runs in your browser and nothing is transmitted.
How to use the JSON Sort Keys
- Paste the document.
- Sort - every object is reordered alphabetically, at every level of nesting.
- Copy the result, and do the same to the other document if you are preparing a diff.
- Note that arrays are left alone: their order is significant, so sorting them would change the data rather than just the text.
Examples
-
Unsorted
{"z":1,"a":{"y":2,"b":3}}
JSON Sort Keys in code
The same operation this tool performs, in the languages you are most likely to need it.
# Sort keys recursively
jq -S . file.json
# The canonical way to diff two JSON files
diff <(jq -S . a.json) <(jq -S . b.json)
# Sort keys AND normalise an array whose order is not meaningful
jq -S '.items |= sort_by(.id)' file.json
function sortKeys(value) {
if (Array.isArray(value)) return value.map(sortKeys);
if (value === null || typeof value !== "object") return value;
return Object.fromEntries(
Object.keys(value).sort().map((k) => [k, sortKeys(value[k])])
);
}
const canonical = JSON.stringify(sortKeys(JSON.parse(raw)), null, 2);
// A stable cache key or checksum over a JSON document needs this -
// without it, the same data hashes differently depending on key order.
const key = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode(JSON.stringify(sortKeys(data)))
);
import json
# sort_keys handles it recursively
print(json.dumps(json.loads(raw), indent=2, sort_keys=True))
# Deterministic bytes for hashing or signing
canonical = json.dumps(data, sort_keys=True, separators=(",", ":"),
ensure_ascii=False).encode("utf-8")
When you need this
- Normalising two documents so a diff shows real changes rather than reordering.
- Producing deterministic bytes to hash, sign or use as a cache key.
- Keeping a JSON file checked into git stable, so unrelated commits stop touching it.
- Making a large config file easier to scan by putting keys in a predictable place.
- Reducing review noise when a serialiser upgrade changes emission order.
Common problems and what causes them
- Expecting arrays to be sorted too
- Arrays are ordered in JSON, so their order is data. This sorts object keys only. If an array's order is not meaningful in your case, sort it explicitly by a stable field - and note that doing so does change the document.
- Assuming sorted keys are enough for a signature
- Key order is one source of non-determinism; number formatting, unicode escaping and whitespace are others. If you are signing JSON, use a real canonicalisation such as RFC 8785 rather than sort_keys alone.
- A consumer that depends on key order
- The specification says objects are unordered, but parsers generally preserve insertion order and a small number of systems have quietly come to rely on it. Check before sorting a document that feeds something you do not control.
- Sorting changing how numbers are written
- Sorting means parse-then-re-serialise, so 1.0 becomes 1 and very large integers can lose precision. If exact number text matters, this transform is not lossless.
FAQ
- Does sorting keys change my JSON data?
- No - objects are unordered by specification, so the parsed value is identical. Only the serialised text changes, which is precisely why it helps with diffing and hashing.
- Why sort keys before diffing?
- Because different serialisers emit the same data in different orders, and a line-based diff then marks the entire document as changed. Sorting both sides first leaves only the real differences.
- Are arrays sorted as well?
- No, and they should not be. Array order carries meaning in JSON, so reordering one changes the document. Sort arrays yourself, by a stable key, only where order is genuinely insignificant in your data.
- Is sorting keys enough to canonicalise JSON for signing?
- Not on its own. You also need deterministic number formatting, string escaping and whitespace. RFC 8785 (JSON Canonicalization Scheme) specifies all of it, and there are implementations for most languages.
- Are arrays reordered?
- Array element order is preserved; only object keys are sorted.