JSONの仕様では、オブジェクト内のキーの順序は形式的には定義されていません — {"a": 1, "b": 2}と{"b": 2, "a": 1}は同じデータを表します。しかし実際には、人にとってもそのデータを扱うツールにとっても、キーの順序は依然としてしばしば重要です。
なぜキーをソートするのか
- Diff。同じデータを持つ2つのJSONドキュメントのキー順序が異なると、テキストdiffは誤った差分を表示します。ソートによりこの問題は解消されます。
- 決定的な出力。同じオブジェクトを何度もシリアライズする場合(ハッシュやキャッシュキーの生成など)、ソートされたキーは毎回同じ結果を保証します。
- 可読性。アルファベット順にソートされたオブジェクトは、特に大きな構造の中で特定のフィールドをすばやく見つけやすくなります。
再帰的なソート
結果を予測可能にするため、ソートは通常再帰的に適用されます — トップレベルのキーだけでなく、任意の深さにあるすべてのネストしたオブジェクトのキーにも適用されます。配列内の要素の順序は変更されません。配列では要素の順序自体がデータの意味のある一部だからです。
不要な場合
JSONがプログラムだけに使われ、人間やdiffツールが関与しない場合、キーのソートは通常実用上のメリットをもたらしません — パーサーはフィールドの順序にかかわらずオブジェクトを同じように読み取ります。
漢字には「アルファベット順」という概念がそもそも存在しない
ひらがな・カタカナは五十音順という明確な並び順を持ちますが、漢字そのものにはアルファベットのような固有の順序がありません。日本語の辞書や電話帳で漢字の項目を並べる際は、実際には見出し語の「読み」(ふりがな)を五十音順で比較しており、漢字のUnicodeコードポイント自体を単純に比較しても、実用的な五十音順にはまったくなりません。つまりJSONキーが漢字を含む場合、正しい辞書順に並べるには読み仮名という追加のメタデータが必要であり、これはラテン文字やハングルの並べ替えとは根本的に異なる問題です。
ソートとロケール
ラテン文字だけでなく他の文字を含むキーのアルファベット順ソートは、文字をバイト単位(Unicodeコードポイント)で比較するか、言語の規則を考慮した照合(locale-aware collation)で比較するかによって結果が変わります。例えば、バイト単位の比較はアルファベットに関係なく大文字を小文字より先に並べますが、ロケールを考慮したソートはキーを異なる順序に並べることがあります。