mygems

JSON のエラーを直す方法: よくあるエラーをすべて解説

Unexpected token、末尾カンマ、シングルクォート、使えない場所のコメント。各 JSON エラーの意味、行の見つけ方、直し方を解説します。

執筆: mygems ·

JSON は、ルールを知るまでは細かすぎると感じるほど厳格です。末尾のカンマは不可。引用符はダブルクォートのみ。コメントは不可。キーは必ず引用符で囲みます。どれか 1 つでも破ると、ドキュメント全体が拒否され、文字位置を示すだけで何が悪いのかはほとんど教えてくれないメッセージが表示されます。

このページでは、エラーメッセージを原因に、原因を修正方法に結び付けて説明します。

最短の答え

  1. 位置を確認する。 どのパーサーも行と列、または文字オフセットを報告します。そこへ移動してください。間違いはその位置か、そのすぐ手前にあります。
  2. よくある 5 つを探す。 末尾のカンマ、シングルクォート、引用符のないキー、コメント、項目間のカンマ抜けです。
  3. エラーが位置 0、または 1 行目 1 列目の場合、 問題は JSON そのものではありません。HTML のエラーページ、空のレスポンス、バイトオーダーマーク (BOM) など、別のものを受け取っています。

どのマシンでも正確な位置を調べるには次を実行します。

python3 -m json.tool broken.json
jq . broken.json

エラーメッセージの読み方

同じ間違いでも、言語ごとに表示が異なります。自分の環境のメッセージを探し、原因を確認してください。

メッセージ(省略形)発生場所よくある原因
Unexpected token '<', "<!DOCTYPE"... is not valid JSONJavaScriptJSON ではなく HTML ページを受け取った。詳しくは後述
Unexpected end of JSON inputJavaScriptレスポンスが空、またはファイルが途中で切れている
Expected double-quoted property nameJavaScript} の前の末尾カンマ、または引用符なし・シングルクォートのキー
Unexpected non-whitespace character after JSONJavaScript2 つのドキュメントが連続している、または閉じ括弧の後にゴミがある
Bad control character in string literalJavaScript文字列内に生のタブまたは改行がある
Expecting value: line 1 column 1 (char 0)Python入力が空、または JSON ではない
Expecting property name enclosed in double quotesPython末尾カンマ、シングルクォート、または引用符なしのキー
Expecting ',' delimiterPython項目またはメンバー間のカンマ抜け
Extra dataPythonファイルに複数のドキュメントがある(NDJSON によくある)
Invalid control characterPython文字列内に生のタブまたは改行がある
Unexpected UTF-8 BOMPythonファイル先頭に見えないバイトオーダーマークがある

原因を 1 つずつ確認する

末尾のカンマ

{ "name": "Ada", "role": "admin", }

JavaScript のコードでは許されますが、JSON では禁止です。パーサーは次のキーを期待しているところで } に達します。最後のカンマを削除してください。手作業で編集した設定ファイルや、文字列連結で JSON を組み立てるコードがよくある原因です。

シングルクォート

{ 'name': 'Ada' }

JSON の文字列は常にダブルクォートを使います。多くは、Python の dict を json.dumps() ではなく print() で出力したことが原因です。本当の修正は出力元のコードにあります。文字列フォーマットではなく、JSON ライブラリでシリアライズしてください。

引用符のないキー

{ name: "Ada" }

JavaScript としては有効ですが、JSON としては無効です。すべてのキーを引用符で囲んでください。

コメント

{ "port": 8080 // default }

JSON にコメントはありません。ただし「直す」前に注意してください。コメントがあって当然のファイルもあります。tsconfig.json、VS Code の settings.json など多くの設定ファイルは JSONC(コメント付き JSON)や JSON5 で、それを読むツールはコメントを受け付けます。該当するなら、問題はファイルではなく、それを渡している厳格なパーサーの側です。

カンマ抜け

{ "a": 1 "b": 2 }

パーサーは "b" で報告します。つまり間違いの後ろです。正常なキーを指してエラーが出たときは、その前の行の末尾を確認してください。

JSON にない値

NaN、Infinity、undefined、007 のような先頭ゼロの数値はすべて無効です。0xFF のような 16 進数も同様です。受け取る側の期待に応じて、null、文字列、通常の 10 進数を使ってください。

文字列内の生の改行とタブ

文字列内の改行は \n、タブは \t とエスケープする必要があります。引用符の中の実際の改行は無効です。複数行の値を JSON ファイルに手で貼り付けたときによく起こります。

バックスラッシュ

"C:\new\folder" のような Windows のパスは、\n や \f がエスケープシーケンスなので壊れます。バックスラッシュをすべて二重にして "C:\\new\\folder" にするか、スラッシュを使ってください。

全角の引用符(カーリークォート)

“name” は文字列に見えますが、そうではありません。これは装飾的な引用符で、" ではありません。ドキュメント、チャットアプリ、スライドからコピーした JSON や、iPhone・iPad での入力時にスマート句読点が直線の引用符を置き換えることで混入します。iOS で JSON を編集する前に、設定 → 一般 → キーボードでオフにしてください。

「位置 0」のエラー: JSON ではない

エラーが最初の文字にある場合、間違っているのは構文ではなく内容です。

  • 位置 0 の < は、HTML を解析したことを意味します。サーバーがエラーページ、ログインページ、404 を返し、コードがそれを JSON として読もうとしました。解析の前に、生のレスポンスとステータスコードをログに出してください。
  • 入力が空 の場合、レスポンスに本文がありませんでした。多くは 204 No Content、またはサーバーが応答する前に失敗したリクエストです。
  • 先頭の見えない文字 は、たいてい Windows のエディターが付けた UTF-8 のバイトオーダーマークです。Python ではファイルを encoding="utf-8-sig" で開き、それ以外では BOM なしの UTF-8 で保存し直してください。

NDJSON は壊れた JSON ではない

1 行に 1 つの JSON オブジェクトを書いたファイル(.jsonl、.ndjson、ログ出力)は、2 行目の先頭で「Extra data」や「Unexpected non-whitespace」になります。各行は単独では有効です。1 行ずつ解析するか、この形式に対応したツールを使ってください。jq -c . file.jsonl はすべての行を読み込みます。

自動で修復する

よくあるミス(末尾カンマ、シングルクォート、引用符のないキー、コメント)は、妥当な解釈が 1 つしかないので、自動修復しても安全です。次のようなツールがあります。

  • jsonrepair。JavaScript ライブラリ兼コマンドラインツールです。
  • ほとんどのコードエディター。JSON5 や「fix JSON」拡張機能を使います。
  • 入力中に検証する JSON エディターアプリ。

ファイルが途中で切れている場合、自動修復は安全ではありません。修復ツールは開いたままの括弧を閉じ、データが欠けた有効なドキュメントを返します。代わりに、もう一度取得するか、エクスポートし直してください。

iPhone と iPad では、Smart Json がエラーを行と列つきの分かりやすい言葉で表示します。Go でカーソルがその位置に移動し、Fix をタップするだけで、コメント、末尾カンマ、シングルクォート、引用符のないキーをまとめて修復します。

エディターに表示された圧縮済みの JSON。1 行目 2 列目で「Expected a quoted key but found a stray character」と表示するバナーと、Go と Fix のボタン
エラーとその位置、そして修正
JSON Editor: Smart JsoniPhone・iPad

JSON のエラーを行・列つきの分かりやすい言葉で示し、その位置へジャンプして、コメント、末尾カンマ、シングルクォート、引用符のないキーをワンタップで修復します。

できること

そもそも壊さないために

無効な JSON ファイルのほとんどは、手書きか文字列連結で作られたものです。JSON はシリアライザー(json.dumps、JSON.stringify、JSONEncoder)で生成し、手で編集したファイルはコミット前に検証してください。pre-commit フックで jq . file.json > /dev/null を実行すれば、上記のミスは他の人の目に触れる前に見つかります。

よくある質問

「Unexpected token < in JSON at position 0」とはどういう意味ですか?
JSON ではなく HTML を解析しています。サーバーがエラーページ、ログインページ、404 を返し、コードがそれを JSON として読もうとしました。パーサーを呼ぶ前に、生のレスポンスとステータスコードをログに出してください。
JSON で末尾のカンマは使えますか?
いいえ。オブジェクトや配列の最後の項目の後ろにカンマがあると、JavaScript のコードでは許されても、JSON としては無効になります。最後のカンマを削除してください。JSON5 や JSONC では許されますが、標準の JSON パーサーでは許されません。
JSON にコメントは書けますか?
標準の JSON では書けません。JSONC(VS Code や tsconfig.json で使用)や JSON5 など、JSON をベースにした一部の設定形式ではコメントが許され、それらを読むツールも受け付けます。厳格な JSON パーサーは拒否します。
JSON のどこが無効なのかを調べるには?
位置を報告するバリデーターに通します。コマンドラインなら python3 -m json.tool file.json または jq . file.json、あるいはエラーに下線を引く JSON エディターを使います。間違いは報告された位置か、そのすぐ手前、たいていは前の行の末尾にあります。
正しく見えるのに JSON が無効になるのはなぜですか?
見た目は正しいのに違う文字を探してください。直線ではなくカーリークォート(ドキュメントからのコピーや iPhone での入力でよく起こります)、ファイル先頭の見えないバイトオーダーマーク、文字列内の生のタブなどです。
無効な JSON は自動で修正できますか?
よくあるミスなら可能です。末尾カンマ、シングルクォート、引用符のないキー、コメントは、それぞれ解釈が 1 つに決まるので、jsonrepair などのツールで安全に直せます。途中で切れたファイルは安全に直せません。修復ツールが括弧を閉じて、欠けたデータを黙って失うからです。

mygems — Smart Json を開発。手書きのパーサーがこれらのエラーを行と列つきで示し、よくあるものは修復します。