· 4 min read
How to Sort a JSON Array by Any Key
Manesh Jayawardhana
CIO & Co-founder
The list sorts as 1, 10, 100, 11, 2, 20, 3. Everyone recognises it, everyone knows why, and it still catches people out — because the field looked like numbers and was stored as strings.
Sorting is one of those operations where the mechanics are trivial and the type handling is the entire problem.
Why numbers stored as text sort wrongly
String comparison works character by character. Comparing “10” with “2”, the first characters are “1” and “2”, and “1” comes first — so “10” sorts before “2” regardless of the values.
The values that arrive as strings and look numeric are predictable: identifiers from an API, version numbers, anything read from a CSV, and any field a form submitted without coercion.
Detecting the type before sorting is the fix, and seeing the detected type is what tells you whether the result will be what you expect. A field detected as text that you believed was numeric is the whole diagnosis.
| Values | As text | As numbers |
|---|---|---|
| 2, 10, 1 | 1, 10, 2 | 1, 2, 10 |
| v1.9, v1.10 | v1.10, v1.9 | Needs version comparison |
| 2026-03-04, 2026-11-02 | Correct — ISO sorts | Correct |
| 04/03/2026, 02/11/2026 | Wrong | Needs parsing |
ISO dates are the exception worth knowing: YYYY-MM-DD sorts correctly as text, because the components are in descending order of significance and zero-padded. That is not an accident — it is why the format is specified that way.
Multi-key sorting
One key rarely gives the order you want. Sorting employees by department produces the right grouping and arbitrary order inside each group.
A second key breaks ties within the first, a third within the second. Department then surname then first name gives a list a human can read.
Sort stability matters here. A stable sort preserves the relative order of items that compare equal, which means you can sort by the secondary key first and then by the primary, and the secondary order survives inside each group. An unstable sort scrambles it, so the multi-key comparison has to be done in one pass.
Where nulls go
Every sort meets missing values, and there is no universally right answer.
Nulls last is the usual choice for a display list. Records with data appear first and incomplete ones sink to the bottom where they do not interrupt.
Nulls first suits review queues, where missing data is what you are looking for and burying it defeats the purpose.
Treating null as zero or empty string is what happens by default in some implementations and is almost always wrong — it interleaves missing values with real ones, which makes them invisible.
The important part is that it is a decision. A sort that silently places nulls somewhere is a sort you will misread once.
Sorting text is locale-dependent
A subtlety that surfaces the moment data is not plain English.
Default string comparison in most languages compares character codes, which puts uppercase before lowercase and places accented characters after the entire unaccented alphabet. So a list sorted that way puts “Zebra” before “apple” and “Ávila” after “Zurich”.
A locale-aware comparison handles case and accents the way a reader expects, and different locales order differently — the same list sorts differently in Swedish and German.
For a display list, locale-aware sorting is nearly always what you want. For a stable machine-readable ordering, code point comparison is more predictable. Choosing deliberately avoids a list that looks wrong to the people reading it.
Common mistakes to avoid
- Sorting numeric strings without coercing them.
- Sorting non-ISO dates as text.
- Assuming a sort is stable when the implementation does not guarantee it.
- Letting nulls fall wherever the default puts them.
- Sorting a large array in the browser without checking the size first — this is fine for thousands of records and not for millions.
How to do it with JSON Array Sorter
The JSON Array Sorter shows the detected type before sorting.
- Paste the array of objects.
- Choose the sort key, and a second for tie-breaking.
- Check the detected type — a numeric field detected as text is why the order looks wrong.
- Decide where nulls belong rather than accepting a default.
Other developer tools are in the tools directory.
Frequently asked questions
Why did 10 sort before 2?
Because they were compared as strings, character by character, where “1” precedes “2”. Numeric fields stored as text need a numeric comparison, which is why the detected type is shown.
Do ISO dates sort correctly as text?
Yes. YYYY-MM-DD is zero-padded and ordered from most to least significant, so lexical order matches chronological order. Other date formats do not have that property.
How are nulls handled?
However you choose. Last is the usual convention for display lists; first suits review queues where missing data is the thing you are looking for.
Final thought
Look at the detected type before reading the order. Almost every sort that comes out wrong is a number that was stored as a string.