
JSON.parse での「予期しないトークン」エラーの解決:あらゆる原因を網羅した実践ガイド
公開日 2026年7月23日
SyntaxError: Unexpected token X in JSON at position N は JavaScript で最もよく見られるエラーの一つですが、最も役に立たないエラーの一つでもあります。このエラーは、パーサーが処理を中断した「場所」は教えてくれますが、「理由」は教えてくれないからです。ここでは、実際にこのエラーを修正する方法をご紹介します。
ステップ 1: 位置番号を確認する
JSON.parse は、文字列の先頭から 0 を起点として文字数を数えます。JSON が変数から取得されたものである場合、他の処理を行う前に、その位置周辺の正確なスライスをログに出力してください:
try {
JSON.parse(raw);
} catch (e) {
const match = e.message.match(/position (\d+)/);
if (match) {
const pos = Number(match[1]);
console.log(raw.slice(Math.max(0, pos - 20), pos + 20));
}
}
この一節だけで、JSONの構文に関するどんなアドバイスよりも多くのエラーを解決できます。というのも、ほとんどの「予期しないトークン」エラーは、実際には 「文字列に実際に何が含まれているかわからない」というエラーだからです。コピー&ペーストによる末尾の空白、テンプレートリテラルからの余分な改行、あるいは先頭(位置0、トークン — ほとんどのエディタでは表示されません)にあるバイト順マーク(BOM)などが原因です。
実際に発生する頻度順に並べた7つの原因
- 末尾のコンマ。
{"a": 1, "b": 2,}— JavaScriptのオブジェクトリテラルでは有効ですが、JSONでは無効です。}や]の直前にあるコンマが、最も一般的な原因です。 - 二重引用符の代わりに一重引用符を使用している。
{'a': 1}は JavaScript であり、JSON ではありません。JSON では、キーと文字列値の両方を二重引用符で囲む必要があり、例外はありません。 - 引用符で囲まれていないキー。
{a: 1}— これもまた、JavaScript では有効ですが、JSON では無効です。 すべてのキーには引用符が必要です。 - 有効なJSONではないJSの値。
undefined、NaN、関数、またはコメント (// like this) — これらはいずれもJSON仕様には存在せず、JavaScriptにのみ存在します。 - 二重エンコード。
JSON.stringify()を 2 回呼び出したか、すでにオブジェクトとなっている文字列を解析しようとしています —.parse()を呼び出す前に、typeof raw === 'string'で確認してください。 - 空の文字列または
undefinedのレスポンス。 フェッチが静かに失敗した場合、または空のボディを返した場合、JSON.parse("")はUnexpected end of JSON inputという、異なるが関連するエラーをスローします。解析する前にresponse.okを確認し、生のボディをログに記録してください。 - コピー&ペーストによる BOM または不可視文字。 PDF、Word 文書、またはターミナル出力から JSON を貼り付けると、BOM や、通常の文字と見分けがつかない非改行スペースが含まれてしまうことがあります。
最も手っ取り早い対処法:デバッグする前に検証する
生のエラーメッセージを1文字ずつ読み解くのは時間がかかります。文字位置番号から推測するのではなく、無効な文字を直接ハイライト表示してくれるフォーマッタに正確な文字列を貼り付けてください。そうすれば、「812文字目付近」という曖昧な表現が、「ここにある、この特定の欠落した括弧」という明確な指摘に変わります。(リンクは以下を参照。)
JSONが実際に有効であるにもかかわらず失敗する場合
フォーマッタでJSONの構文が正しいことが確認されたにもかかわらず、JSON.parseが依然として例外をスローする場合は、渡している文字列が、あなたが思っているものとは異なるものです。 最も一般的な原因は、解決済みの本体ではなく、 Response オブジェクトに対して .parse() を呼び出していることです。
// Wrong — parses "[object Response]", not the body
const data = JSON.parse(await fetch(url));
// Right
const data = await (await fetch(url)).json();
// or, if you need the raw text first:
const text = await (await fetch(url)).text();
const data = JSON.parse(text);
クイックリファレンス
| 症状 | 考えられる原因 |
|---|---|
Unexpected token } |
閉じ中括弧の前にコンマが残っている |
Unexpected token ' |
ダブルクォートではなくシングルクォートが使用されている |
Unexpected token a (または任意の文字) |
引用符で囲まれていないオブジェクトキー |
Unexpected end of JSON input |
空の文字列、切り詰められたレスポンス、または閉じられていない括弧 |
Unexpected token (位置 0) |
コピー&ペーストされたファイル、または Windows で保存されたファイルに由来するバイト順マーク |
これらについて、何も暗記する必要はありません。修正方法は常に同じ3つのステップです。報告された位置周辺のスライスをログに記録し、フォーマッタにかけ、フラグが立った1文字を修正するだけです。