JSON Toolkit

JSON パースエラーの直し方:Unexpected token を順に切り分ける

要点:JSON.parse のエラーを行と文字位置に変換し、末尾カンマ、単一引用符、コメント、制御文字、BOM、途中切れの六つの原因を順に除外します。

初級約 12 分で読めます2026-10-30 公開2026-11-01 更新
JSON パースエラーを診断するためのカバー画像

要点:パースエラーが出たら、報告された行と列を読んで最初の不正な文字を特定し、引用符の欠落、カンマの欠落、末尾カンマ、BOM、途中切れのどれかを判断しましょう。文書全体を最初から読み直す必要はありません。

エラーメッセージは「何が間違っているか」を教えてくれません。「パーサーがこれ以上進めなくなった場所」だけを教えます。その二つはしばしば同じ場所ではありません。

1. まずエラーを座標に変換する

同じ壊れた JSON でも、言語によってまったく違うエラーになりますが、すべて「何行目の何文字目か」に変換できます。

環境 典型的なエラー 読み方
ブラウザ / Node Unexpected token } in JSON at position 42 position は 0 始まりの文字オフセットで、行番号ではない
Node 20+ Unexpected non-whitespace character after JSON at position 42 前半は正しく、余分な内容が 42 以降から始まるという意味
Java Jackson Unexpected character ('}' (code 125)): was expecting ... at [Source: (String)..."..." ; line: 3, column: 1] 行と列を直接示す。最も使いやすい
Python json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 1 (char 42) char はオフセット。行と列が重要
Go invalid character '}' looking for beginning of object key string 文字しか示さないので、自分で遡って位置を特定する

位置が分かったら、その JSON をJSON オンラインパーサーに貼り付けます。ツールがカーソルをエラー位置に置き、行番号と列番号を強調表示します。この一手間で、文字を目で追う作業の 90% が省けます。

2. 頻出する六つのエラー

1. 末尾カンマ

{
  "name": "json",
  "version": 1,
}

} の前に余分なカンマがあります。JSON 仕様は末尾カンマを許しませんが、JavaScript のオブジェクトリテラルは許すため、コードからコピーした設定が最も持ち込みやすいです。修正:最後のカンマを削除します。このデータがもともと JS ファイルにあるなら、無理に JSON にせず JSON5 変換に切り替えましょう。

2. 単一引用符と引用符なしキー

{ 'name': 'json' }
{ name: "json" }

JSON の文字列は二重引用符のみを使え、キーも二重引用符付きの文字列でなければなりません。この二つは JSON5 / JavaScript の緩い構文であり、JSON ではありません。文字列内の二重引用符は \"、バックスラッシュは \\ と書きます。

3. コメント

{
  // タイムアウト(ミリ秒)
  "timeout": 3000
}

RFC 8259 の文法にコメントの居場所はありません。コメントを削除するか、.jsonc / .json5 として保存し、コメントをサポートするパーサーを使います。各種「コメント手段」のトレードオフはJSON にコメントを書く方法を参照してください。

4. 文字列内の生の改行と制御文字

{"sql": "SELECT *
FROM t"}

JSON の文字列には生の改行、タブ、制御文字 U+0000–U+001F を含められません。\n、\t、\u0009 と書く必要があります。複数行のテキストを JSON に詰めるときは、先にエディタで一度エスケープするか、JSON 圧縮とエスケープでまとめて処理してください。

5. BOM ヘッダ

Windows のメモ帳で保存した UTF-8 は EF BB BF の 3 バイトを伴います。JSON.parse は BOM に出会うと Unexpected token を報告し、目ではまったく見えません。見分け方:ファイル先頭を 16 進で調べるか、内容をオンラインツールにコピーして最初の文字が  と表示されるか確認します。修正:「UTF-8(BOM なし)」で保存します。

6. 途中で切れた内容

先頭 4096 文字だけを出力したログ、ゲートウェイに切られた API レスポンス、中断されたダウンロード。この類の特徴は「エラーが末尾にある」ことと、括弧の数が合わないことです。まず括弧を数えます。{ と [ の閉じ括弧が合わなければ、構文エラーではなく途中切れです。その場合は何も直さず、完全なデータを取得しに行きましょう。

3. 中国語とエスケープに関する二つの誤検知

中国語が \u4e2d\u6587 になる:これは正しい JSON エスケープであり、文字化けではありません。パース後、値は中国語に戻ります。\u 形式が見えるのは、生の文字列を直接見たときだけです。人に見せる必要があるときは整形ツールで出力すればよく、中国語を URL やログに残さなければならないときにだけエスケープ戦略を気にすれば十分です。

中国語が 涓枃 のような文字化けになる:これはエンコーディングの問題で、JSON の問題ではありません。UTF-8 のバイト列を GBK としてデコードしたときに起こり、「三文字が一つの中国語文字の代わりになる」という規則的なパターンになります。レスポンスヘッダの Content-Type: application/json; charset=utf-8 を確認し、ファイル読み込み時に encoding='utf-8' を明示しているか確認してください。

4. 五分で終わる修復手順

  1. ツールに貼る:まずオンラインパーサーで最初のエラーを特定し、一度に一つだけ直します。
  2. 修正のたびに検証する:変更のたびに再パースします。複数箇所をまとめて直すと、新しいエラーが元のエラーを覆い隠してしまいます。
  3. 一度圧縮する:圧縮で空白を除去して再パースします。これで「構造の誤り」と「空白や改行の問題」を切り分けられます。
  4. 構造を比較する:変更後に突然エラーが出たら、JSON diffで前のバージョンと比較します。違いはたいていカンマ一つです。
  5. フィールド単位で検証する:構文は通るのに業務層が拒否する場合(フィールド欠落、型違い)は、構文問題ではなくJSON Schema 検証の範疇です。

5. 「見た目が同じ」二つの JSON の片方だけパースできる理由

最も多い原因は不可視文字です。全角カンマ ,、全角引用符 “”、非改行スペース U+00A0、ゼロ幅スペース U+200B。画面上では半角の対応物とほとんど見分けがつきませんが、どれも JSON の文法には含まれません。

見分け方は一つだけです。問題の文字の前後をコピーし、コードポイントをバイト単位で調べます。ブラウザのコンソールで次を実行すると、非 ASCII かつ中国語の範囲外にある文字がすべて一覧になります。

[...text].filter((ch) => {
  const code = ch.codePointAt(0);
  return code > 127 && !(code >= 0x4e00 && code <= 0x9fff);
});

出力に 0x201c(左二重引用符)、0xff0c(全角カンマ)、0x00a0 が現れれば、それが犯人です。

6. 修復より予防の方が安い

  • 設定ファイルはコミット前にパースチェックを実行する。CI に一行で足りる:node -e "JSON.parse(require('fs').readFileSync('config.json','utf8'))"。
  • API レスポンスはシリアライズライブラリで生成する。文字列を手で連結しないこと。手組みの文字列こそ末尾カンマと引用符欠落の唯一の発生源です。
  • JSON をログに出すときは、テンプレートに埋め込むのではなく先に JSON.stringify を呼ぶ。中途半端なペイロードが完全なメッセージと誤認されないようにするためです。

FAQ

JSON 構文エラーの位置を素早く特定するには?

パーサーが報告する position または行・列を読みます。position は 0 始まりの文字オフセットで行番号ではなく、Java Jackson と Python は行と列を直接報告します。JSON をJSON オンラインパーサーに貼ると、ツールがカーソルをエラー位置に置き、行と列を強調表示します。エラーが先頭にある場合は、ファイル先頭の BOM と不可視文字を確認してください。

コードからコピーした設定に末尾カンマが付きやすいのはなぜですか?

JSON 仕様は末尾カンマを禁じますが、JavaScript のオブジェクトリテラルは許すため、JS コードからコピーした設定に付いてきやすいのです。修正は最後のカンマを削除するだけです。データがもともと JS ファイルに属するなら、無理に JSON にせず JSON5 変換に切り替える方が適しています。

コメントを含む設定ファイルを通常の JSON としてパースできますか?

いいえ。RFC 8259 の文法にコメントの居場所はないため、そのままパースするとエラーになります。コメントを削除するか、.jsonc / .json5 として保存し、コメントをサポートするパーサーを使ってください。コメント手段のトレードオフはJSON にコメントを書く方法を参照してください。