短い答え
JSONフォーマッターを開き、JSONを枠に貼り付けて、読んでください。整形は打ち込みながら進み、どの言語かは中身から判断され、字下げは指定がなければ半角空白2つです。何もアップロードされません。送る先がそもそも存在しないからです。解析するのは、いま開いているタブの中で動く数百行のJavaScriptです。
以下はすべて、ほかの選択肢のどれかに設定ファイルを貼り付ける前に知っておく値打ちのあることです。整形ツールが変えてよいものは何か、それでも多くのツールが変えてしまうものは何か、そしてファイルがまったく読めないときにエラーをどう読むか。
整形とは何であって、何ではないのか
JSONには文法がほとんどありません。オブジェクト、配列、文字列、数、そしてtrue、false、nullという3つの語だけです。その部品のあいだでは、空白に意味はありません。次のファイルと、
{"name":"thing","tags":["local","offline"]} 次のファイルは、
{
"name": "thing",
"tags": [
"local",
"offline"
]
} 同じ文書です。整形とは前者から後者へ移す作業のことで、仕事はそれで全部です。整形ツールがあなたのファイルに対してそれ以外にすること、つまり並べ替え、丸め、切り捨ては、頼まれてもいないのに文書の中身を変えることです。
そのうち3つは名前を挙げておく値打ちがあるほどよくあります。どれも黙って行われ、そして半日で書いた整形ツールが既定でしてしまうことだからです。
整形ツールが変えてはいけない3つのもの
キーの順序
引っかかるのはこれです。JavaScriptでJSONの整形を書くいちばん素直なやり方は、JSON.parseを呼んでから字下げ付きでJSON.stringifyを呼ぶことですが、この組み合わせは整数に見えるキーの順序を保ちません。
Object.keys(JSON.parse('{"10":"a","2":"b","x":"c"}'))
// ['2', '10', 'x'] 誰かのコードの不具合ではありません。JavaScriptのオブジェクトは、整数のようなキーを先頭に、数の小さい順に置くと仕様で決まっていますし、JSON.parseを通った値はすべてJavaScriptのオブジェクトになります。そうやって作られた整形ツールは、IDやポート番号や年やHTTPステータスコードで引いてあるファイルを並べ替えますし、それをひと言も言わずにやります。
それが問題になるかどうかはファイル次第です。JSONのオブジェクトは原則として順序を持たないので、厳密には何も壊れていません。ただし、リポジトリにある版との差分は膨大になり、レビューは読めたものではなくなり、下流の何かがファイルを順に読んでいるなら挙動が変わります。
数の桁
JSONは数の大きさに上限を定めていませんが、JavaScriptは定めています。どの数も倍精度浮動小数点です。ですから倍精度に読み込んで書き戻す整形ツールは、倍精度に収まらないものをすべて失います。
JSON.stringify(JSON.parse('{"id":123456789012345678901}'))
// {"id":123456789012345680000}
JSON.stringify(JSON.parse('{"size":1e999}'))
// {"size":null} 21桁のID、たとえばTwitterのIDやSnowflakeのID、銀行の照会番号は、別の数になって返ってきますし、倍精度には大きすぎる値はnullになって返ってきます。どちらのファイルも相変わらず読めますが、どちらも出発点のファイルではありません。
抜け道は、数をそもそも解釈しないことです。整形ツールは文書を組むために数の始まりと終わりを知る必要があるだけで、その値は一度も要りません。ですから安全なやり方は、書かれていたとおりの桁をそのまま写すことです。ここの道具はそうしています。
重複したキー
{"a": 1, "a": 2}は正しいJSONですが、規格はどちらが勝つかを決めていません。実際、解析器によって扱いが違います。多くは後のほうを採り、一部は先のほうを採り、いくつかは文書ごと受け付けません。黙ってどちらかを書き出す整形ツールは、その判断をあなたの代わりに下したうえに、2つあったというはるかに有用な事実を隠しています。それはほとんどの場合ファイルの誤りで、しかも見たいはずのものです。
ファイルが読めないとき
うまく読めないJSONの大半は、珍しいものではありません。だいたい6種類のうちのどれかで、そしてエラーがどこかを探せる形で示してくれるなら、どれなのかも分かります。位置 4193のような通し番号では探せませんが、行と桁なら探せます。
- 末尾の余分なコンマ。
{"a": 1,}はJavaScriptでは許され、JSONでは許されません。単独の原因としてはいちばん多く、たいていは一覧の最後の項目を消したあとに残ります。 - 単引用符。
{'a': 1}はJavaScriptのオブジェクトリテラルであって、JSONではありません。文字列もキーも二重引用符で囲みますし、キーは必ず囲みます。 - 引用符のないキー。
{a: 1}、逆方向からの同じ間違いです。ファイルからではなくコードから貼り付けたときに起こりがちです。 - コメント。
// こういうものもJSONではありません。それはJSONCで、VS Codeの設定やtsconfig.jsonが使っていますが、ほかの場所では読めません。コメントをどうしても残すなら、慣例はキーにすることです。"_comment": "..."のように書きます。 - 文字列の中の本物の改行やタブ。これらは
\nと\tとして書かなければなりません。シェルのコマンドや証明書を値の中へ手で貼り付けたときに、たいていここで転びます。 - JSONが許さない数。先頭のゼロ(
01)、裸の小数点(.5)、NaN、Infinity、+1。どれも人が書きますが、どれもJSONではありません。
誤りではないのに誤りに見えるものがひとつ。バイト順マークで始まるファイルです。たいていの編集ソフトでは見えず、空白でもなく、文書のいちばん最初の文字を予期しないものにしてしまいます。見た目に何の問題もないファイルで、エラーが1行1桁目なら、それです。
詰めること、そしてそれが得るものの少なさ
空白を絞り出すのは同じ作業の逆向きで、それで何が手に入るのかは冷静に見ておく値打ちがあります。空白は繰り返しの多いものですし、あなたと読み手のあいだにいるサーバーもブラウザも、応答をすでにgzipやBrotliで圧縮しています。そしてそれらはまさにその種の繰り返しに強いのです。
ですから詰めたJSONは、ファイルとしては3割ほど小さくなっても、回線の上では数パーセントしか小さくならないことがよくあります。本当に元が取れるのは、手前に圧縮がない場所です。データベースの列に入れる値、ログ1行の中の項目、QRコードに詰め込む中身、そしてこれからBase64にしてヘッダーへ入れる文書など。
代償は読みやすさで、そのファイルをリポジトリに入れているなら差分も代償になります。1行のファイルは、中の何かが変わるたびに丸ごと変わるからです。詰めるのは編集ソフトから出すときであって、入れるときではありません。
キーの並べ替えと、してはいけないとき
オブジェクトごとにキーを並べ替えることは、ここでは既定ではなく選べる形にしてあります。それはファイルへの本当の変更ですし、その値打ちはこれから何をするのかにまるごと左右されるからです。
同じことを言っているはずの2つの文書を比べるとき、たとえば2つの環境の設定や、変更前と変更後のAPIの応答を比べるときで、片方がキーを別の順で並べている場合には効きます。先に両方を並べ替えれば、全部の差分が、本当に違う2行だけの差分に変わります。
順序が何かを担っていたときには害になります。package.jsonには何を先に置くかの慣例がありますし、手で書いた設定は関係のある項目をまとめていることが多く、道具にキーを並べ替えさせてからコミットしたファイルは、意味のない巨大なコミットをひとつ生みます。並べ替えるのは写しであって、元のファイルではありません。
知っておく値打ちのある細かい点。ここでの並べ替えは、符号位置ではなくキーの読み方に沿って行うので、item2はitem10より後ではなく前に来ます。符号位置で並べるとitem10が1で始まるものの真ん中に入り込むわけで、それは技術的には正しく、読む人には役に立ちません。
2つのJSONファイルを比べる
確実なやり方は、先に両方を同じように整形することです。同じことを言っている2つの文書でも、片方が詰めてあってもう片方がそうでなければ、全行が違って見えますし、どんな差分表示もその向こうを見ることはできません。
ですから、1つ目を整形し、2つ目を整形し、それからその2つの結果を比べてください。ここでは3つの手順が同じページにあります。比較のタブが整形と同じ枠を共有しているのは、まさにこのためです。2つがキーを別の順で並べているなら、整形するついでに両方を並べ替えてください。比較は、あなたが探していた違いだけに縮みます。
誰もページに書かない部分
JSONの整形ツールを検索すれば、入力欄の付いたサイトが何十と見つかります。その欄に貼り付けることは、アップロードです。クリップボードに入っていたものが何であれ、顧客の住所が入ったAPIの応答でも、接続文字列の入った設定ファイルでも、いま調べていたトークンでも、それはあなたの管理していない機械へ送られ、いまや相手のログであり、相手のエラー報告であり、相手のバックアップです。
これは悪意を疑う話ではありません。まったく善意のサイトでも、アクセスログは残り、アクセス解析は動き、ホスティング業者はいます。いちばん安全なデータは、そもそも出ていかなかったデータです。そして、まるごと文字列の操作でしかない作業について、出ていく理由はひとつもありません。
確認は2つ。そしてこれは同じことを主張するどのサイトでも使えます。ここだけの話ではありません。
- DevToolsを開き、Networkタブを見ながら、何かを整形してみる。あなたの文字が送られているなら、それを運ぶリクエストがあります。それ以外のことが同時に成り立つことはありません。
- インターネットを切って、もう一度やってみる。ブラウザの中で作業する道具は何ともありません。文字をどこかへ送る道具は、その場で、完全に動かなくなります。
両方の長い版と、さらに2つの確認がファイルをアップロードしても大丈夫かにあります。
YAMLやXMLなどは
同じページがXML、HTML、CSS、YAMLを読みますし、JSONとそのうちの最初と最後とのあいだで相互に変換もします。上から持ち越す値打ちのあることが2つあります。同じ話を別の服に着替えさせただけのものだからです。
- YAMLをJSONにするとコメントは失われます。JSONにはコメントを置く場所がないからです。アンカーとエイリアス、つまりYAMLで「同じ節点をもう一度」と言うための仕組みも表現できないので、ここでは当て推量をせずにお断りしています。
-
noは文字列です。YAML 1.1ではyes、no、on、offが真偽値でした。ノルウェーを含む国コードの一覧がfalse入りで返ってきていたのはそのためです。YAML 1.2はそれをやめましたし、ここでも同じです。ただしそれらの語は引用符付きで書き戻します。次にそのファイルを開くのが1.1の読み手かもしれないからです。