← 記事一覧

JSON データの後の予期しない非空白文字: 修正方法

このエラーは完全な JSON 値の後に余分な内容があることを意味します —— 連結されたオブジェクト、1 ブロックとして parse された NDJSON、末尾のゴミ。余分なデータの見つけ方と直し方。

SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data は、パーサが完全な JSON 値を 1 つ読み終えた —— その後にさらに 空白でない内容を見つけた、という意味です。JSON はトップレベルで値をちょうど 1 つしか許さないので、その後ろにあるものはすべてエラーです。「余分なデータ」がどこから来て、どう直すかを説明します。

エラーの見え方

// Firefox
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
  at line 1 column 18 of the JSON data

// V8 (Chrome / Node / Edge)
SyntaxError: Unexpected non-whitespace character after JSON at position 17
SyntaxError: Unexpected token { in JSON at position 17   // 古い表現

// Python(類似)
json.decoder.JSONDecodeError: Extra data: line 1 column 18 (char 17)

位置は有効な値の の最初の文字を指します —— 「余分」はそこから始まります。

なぜ起きるか

原因 1 —— 2 つの JSON 値が連結されている

// ❌ オブジェクトが背中合わせ —— 有効な値の後にさらに続く
{"id":1}{"id":2}
//      ^ 位置 8:JSON データ後の非空白

// ✅ 配列でまとめる
[{"id":1},{"id":2}]

原因 2 —— NDJSON / JSON Lines を 1 塊として parse している

ログファイルやストリーミング API はしばしば 1 行 1 JSON オブジェクト(NDJSON)を出力します。JSON.parse() は最初の行の値だけを読み、次の行で躓きます。

// ❌ ファイル全体に JSON.parse
{"event":"login"}
{"event":"logout"}

// ✅ 行ごとに parse
const rows = text
  .split('\n')
  .filter(Boolean)
  .map((line) => JSON.parse(line));

原因 3 —— 末尾のゴミ、または二重化されたレスポンス

// ❌ 余計な文字、複製された payload、または末尾セミコロン
{"ok":true};
{"ok":true}  // プロキシが追加したデバッグ行
extra

JSON-RPC とフレーミングのあるストリーム

プロトコルを消費している場合 —— stdio 上の JSON-RPC、Language Server Protocol (LSP)、Debug Adapter Protocol —— 複数の JSON メッセージは設計上、同じチャネルを流れます。それぞれ次のメッセージの長さを伝えるフレーミング層を持ち、ちょうど 1 つのバッファで 2 値を parse しようとせずに済むようになっています:

Content-Length: 87\r\n
\r\n
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}Content-Length: 42\r\n
\r\n
{"jsonrpc":"2.0","id":1,"result":{...}}

ルール:Content-Length ヘッダを読み、ちょうど その分のバイトを読み、1 つ の JSON 値を parse し、ループする。チャネル全体を丸ごと飲んで一回で parse すると「unexpected non-whitespace character after JSON data」にぶつかります。中には多数 の値があるからです。

NDJSON では、対応するルールは「\n で split し、各行を parse」です。共通点:JSON メッセージのストリームには常にフレーミング層が必要 —— 単純な連結は正当な JSON ではありません。

修正の手順

  1. 報告された位置へ —— そこから先がすべて「余分」です。最初の完全な値の直後にあるものを確認してください。
  2. 複数の値? リストにしたかったなら [ … ] 配列でカンマ区切りにまとめる。
  3. NDJSON / JSON Lines? 改行で split し、各行を別々に parse —— ファイル全体を一気に parse しない。
  4. 末尾のゴミ? parse 前に余計な文字(セミコロン、複製された payload、デバッグ出力)を取り除く。
  5. ストリーミング? 複数のレスポンスを 1 つのバッファに連結してから parse していないか確認。

よくある質問

「unexpected non-whitespace character after JSON data」とは?

パーサが有効な JSON 値を 1 つ読み、その後にさらに内容を見つけた、という意味です。JSON はトップレベルの値を 1 つしか許さないので、その後の文字は無効です。

複数の JSON オブジェクトをどう parse する?

連結されているなら配列で包む。1 行 1 つ(NDJSON / JSON Lines)なら改行で split し、各行を個別に JSON.parse()

「Unexpected end of JSON input」と同じ?

逆です。本エラーはデータが多すぎる(完全な値の後にさらに);「Unexpected end of JSON input」 はデータが少なすぎる(値が途切れた)。

今すぐ直す