JSON は、ルールを知るまでは細かすぎると感じるほど厳格です。末尾のカンマは不可。引用符はダブルクォートのみ。コメントは不可。キーは必ず引用符で囲みます。どれか 1 つでも破ると、ドキュメント全体が拒否され、文字位置を示すだけで何が悪いのかはほとんど教えてくれないメッセージが表示されます。
このページでは、エラーメッセージを原因に、原因を修正方法に結び付けて説明します。
最短の答え
- 位置を確認する。 どのパーサーも行と列、または文字オフセットを報告します。そこへ移動してください。間違いはその位置か、そのすぐ手前にあります。
- よくある 5 つを探す。 末尾のカンマ、シングルクォート、引用符のないキー、コメント、項目間のカンマ抜けです。
- エラーが位置 0、または 1 行目 1 列目の場合、 問題は JSON そのものではありません。HTML のエラーページ、空のレスポンス、バイトオーダーマーク (BOM) など、別のものを受け取っています。
どのマシンでも正確な位置を調べるには次を実行します。
python3 -m json.tool broken.json
jq . broken.json
エラーメッセージの読み方
同じ間違いでも、言語ごとに表示が異なります。自分の環境のメッセージを探し、原因を確認してください。
| メッセージ(省略形) | 発生場所 | よくある原因 |
|---|---|---|
Unexpected token '<', "<!DOCTYPE"... is not valid JSON | JavaScript | JSON ではなく HTML ページを受け取った。詳しくは後述 |
Unexpected end of JSON input | JavaScript | レスポンスが空、またはファイルが途中で切れている |
Expected double-quoted property name | JavaScript | } の前の末尾カンマ、または引用符なし・シングルクォートのキー |
Unexpected non-whitespace character after JSON | JavaScript | 2 つのドキュメントが連続している、または閉じ括弧の後にゴミがある |
Bad control character in string literal | JavaScript | 文字列内に生のタブまたは改行がある |
Expecting value: line 1 column 1 (char 0) | Python | 入力が空、または JSON ではない |
Expecting property name enclosed in double quotes | Python | 末尾カンマ、シングルクォート、または引用符なしのキー |
Expecting ',' delimiter | Python | 項目またはメンバー間のカンマ抜け |
Extra data | Python | ファイルに複数のドキュメントがある(NDJSON によくある) |
Invalid control character | Python | 文字列内に生のタブまたは改行がある |
Unexpected UTF-8 BOM | Python | ファイル先頭に見えないバイトオーダーマークがある |
原因を 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 のエラーを行・列つきの分かりやすい言葉で示し、その位置へジャンプして、コメント、末尾カンマ、シングルクォート、引用符のないキーをワンタップで修復します。
できることそもそも壊さないために
無効な JSON ファイルのほとんどは、手書きか文字列連結で作られたものです。JSON はシリアライザー(json.dumps、JSON.stringify、JSONEncoder)で生成し、手で編集したファイルはコミット前に検証してください。pre-commit フックで jq . file.json > /dev/null を実行すれば、上記のミスは他の人の目に触れる前に見つかります。