PC・モバイルのトラブル

よくあるJSONエラー:末尾カンマ、引用符、Unexpected token

無効なJSONを直す:末尾カンマ、単引用符、引用符なしのキー、Unexpected token。JSON.parseが失敗する理由と検証方法。

要点

JSONエラーの多くは厳しい文法から来る。末尾カンマ、単引用符、引用符なしのプロパティ名、欠けたカンマ、括弧の不一致、不正なエスケープ、コメントだ。

JSONはJavaScriptオブジェクトに似て見えるが、より厳しい。プロパティ名と文字列には二重引用符が必要だ。

Unexpected tokenと出ても、示された文字は解析が止まった位置であり、元の誤りが始まった場所とは限らない。

JSONがinvalidと出た。壊れたファイル形式というより、小さな文法の問題が多い。次の七つがUnexpected tokenの大半を起こす。

JSONはなぜ壊れやすいのか

JSONは文法が厳しいデータ形式だ。JavaScriptのオブジェクトリテラルは似て見えても、そのままでは無効なJSONになり得る。標準JSONではプロパティ名と文字列に二重引用符が必要で、末尾カンマは不可、コメントは形式に含まれない。

1. 末尾カンマ(Trailing Commas)

最後のプロパティの後の余分なカンマが問題だ。標準JSONはこれを許さない。

無効

{
  "name": "Alex",
  "age": 30,
}

有効

{
  "name": "Alex",
  "age": 30
}

配列も同じだ。最後の要素の後のカンマを外す。

無効

[
  "red",
  "green",
]

有効

[
  "red",
  "green"
]

2. 二重引用符の代わりに単引用符

JavaScriptは単引用符をよく受け付ける。JSONは受け付けない。プロパティ名も文字列値も二重引用符でなければならない。

無効

{
  'name': 'Alex'
}

有効

{
  "name": "Alex"
}

3. 引用符なしのプロパティ名

JavaScriptではnameのように引用符なしで書けることがある。JSONではすべてのプロパティ名を二重引用符の文字列にする。

無効

{
  name: "Alex",
  age: 30
}

有効

{
  "name": "Alex",
  "age": 30
}

4. 値の間のカンマ漏れ

プロパティと配列要素の間にはカンマが必要だ。パーサーは欠けたカンマそのものではなく、次の引用符や括弧でUnexpected tokenを出すことがある。

無効

{
  "name": "Alex"
  "age": 30
}

有効

{
  "name": "Alex",
  "age": 30
}

5. 括弧の不足や余分

オブジェクトは { }、配列は [ ] を使う。入れ子のJSONでは ] が欠けたり } が余分だったり、両者が入れ替わると失敗する。開きと閉じの対を数える。

無効

{
  "items": [1, 2
}

有効

{
  "items": [1, 2]
}

6. 不正なエスケープ

JSON文字列の中で、バックスラッシュはエスケープを始める。"、\、\n などは有効だ。Windowsパスを C:\Users と書くと不正:\U は合法なJSONエスケープではない。バックスラッシュを二重にするか、パーサーはその文字で止まる。

無効

{"file":"C:\Users\Alex"}

有効

{"file":"C:\\Users\\Alex"}

7. JSON内のコメント

標準JSONにコメントはない。一部の設定ツールは // や /* */ を受け付ける(JSONC、JSON5など)。それは標準JSONではなく、JSON.parseは拒否する。

無効

{
  // user name
  "name": "Alex"
}

Unexpected tokenとは何か

パーサーが、その位置では許されない文字に出会ったという意味だ。報告される地点は読み取りが止まった場所だ。手前でカンマを落とすと、次のプロパティの引用符でエラーになることがある。文言はランタイムで違う。どのブラウザも同じ文を出すとは限らない。

Unexpected end of JSON inputとは何か

値が完了する前にテキストが終わった。欠けた } や ]、途中で切れた入力、空の本体、途中で切れたAPI応答が典型だ。原因は一つに限らない。

JSON.parse()はなぜ失敗するか

JSON.parse()は有効なJSONテキストだけを受け付ける。これは成功する:

const text = '{"name":"Alex"}';
const data = JSON.parse(text);

これは失敗する。単引用符はJSONではない:

const text = "{'name':'Alex'}";
JSON.parse(text);

正確なエラー文はJavaScriptランタイムに依存する。メッセージはヒントとして扱い、その位置付近のカンマ、引用符、括弧を調べる。

JSONはJavaScriptオブジェクトと同じではない

JavaScriptのオブジェクトリテラルは { name: 'Alex' } のように書ける。有効なJSONは { "name": "Alex" } のように、二重引用符の名前と文字列、末尾カンマなし、コメントなしでなければならない。

  • JSONテキスト
  • パーサーがトークンを読む
  • 有効なデータ、または Unexpected token
エラー印は解析が止まった位置であり、本当の誤りより後かもしれない。

JSONエラーを早く見つける方法

この順で進める。ファイル全体を書き直して始めない。

  1. validatorにJSONを通す。
  2. 最初に報告されたエラーを読む。
  3. 報告位置より少し手前を見る。
  4. カンマを確認する。末尾と欠けたもの。
  5. 引用符を確認する。二重引用符のみ。
  6. { } と [ ] を合わせる。
  7. 文字列内のバックスラッシュエスケープを確認する。
  8. strict JSONが必要ならコメントを除く。

よくある修正の早見:

問題 修正
末尾カンマ最後の項目の後のカンマを消す。
単引用符名前と文字列に二重引用符を使う。
引用符なしのキープロパティ名を二重引用符で囲む。
欠けたカンマプロパティや配列要素の間にカンマを入れる。
欠けた括弧すべての { } と [ ] の対を閉じる。
不正なエスケープ合法なエスケープを使うか、パスのバックスラッシュを二重にする。
コメント標準JSONなら // と /* */ を除く。

ブラウザでJSONを検証して整形する

NEXNARA JSON整形・検証・比較はこの端末でJSONを確認できる。

検証、2スペース・4スペース・タブでの整形、minify、二つの文書の比較(JSON Diff)、.jsonファイルを開ける。解析はブラウザのJSON.parseであり、evalは使わない。

5 MBより大きい文書は遅くなることがある。15 MBより大きいテキストはブラウザで処理しないので、ページが応答したままになる。

JSONの処理そのものはブラウザ内で行われる。このツールではテキストをNEXNARAサーバーへ送らない。広告や他のサイト機能はネットワークを使う。それは処理とは別だ。

無効なJSONを確認するならJSON整形・検証・比較を開き、テキストを貼り付けてほしい。

FAQ

JSONが Unexpected token と言うのはなぜ?

パーサーがその位置で許されない文字に出会った。本当の誤り—欠けたカンマや単引用符—はその直前にあることが多い。

JSONで末尾カンマは許される?

いいえ。標準JSONは最後のプロパティや配列要素の後のカンマを許さない。JavaScriptのオブジェクトリテラルはしばしば許す。

JSONに単引用符は使える?

いいえ。プロパティ名と文字列は二重引用符でなければならない。

JSONにコメントを含められる?

標準JSONではできない。一部のツールはコメント付きのJSONCやJSON5を受け付けるが、JSON.parseはそれでも拒否する。

JSON.parse()はなぜ失敗する?

文字列が有効なJSONではないからだ。末尾カンマ、単引用符、引用符なしのキー、コメント、途中で切れた値が典型だ。正確なメッセージはランタイムに依存する。

JSONが有効かどうかはどう確認する?

JSON整形・検証・比較のようなvalidatorに貼るか、コンソールでJSON.parseを呼ぶ。例外が出れば、そのテキストは有効なJSONではない。