← 記事一覧

JSON の末尾カンマ: なぜ { "a": 1, } はエラーになるか

JSON オブジェクトや配列の最後の要素の後に余分なカンマがあるだけで SyntaxError。JSON が末尾カンマを禁じる理由、どこから来るか、取り除き方を学ぶ。

完全に妥当に見える JSON を書いたのに —— すべてのキーは引用符付き、すべての値は妥当 —— JSON.parse() はそれでも SyntaxError を投げる。犯人はほぼ常に末尾カンマ:オブジェクトや配列の最後の項目の後に座っているあの余計な ,。本記事では JSON がなぜそれを禁じるか、どこから紛れ込むか、どう取り除くかを解説します。

末尾カンマとは?

末尾カンマ(「ダングリングカンマ」「ファイナルカンマ」とも)はリストの 最後 の項目の後に現れるカンマで —— 閉じ括弧の前に何も続かない。

// オブジェクト内の末尾カンマ
{
  "name": "Ada",
  "score": 98,   // ← このカンマには次の項目がない
}

// 配列内の末尾カンマ
[1, 2, 3,]
//       ^ 同じ問題

上の両方の例は JSON.parse() に渡すと SyntaxError を投げます。

なぜ JSON は末尾カンマを禁じるか?

JSON 文法(RFC 8259 で定義)はカンマを要素間の 区切り として指定 —— 必ず両側に値が必要。JSON オブジェクトの形式規則はこうです:

object = "{" [ member *( "," member ) ] "}"
member = string ":" value

カンマの後には別の member が続かなければならない。カンマの後に何も無ければ文法違反。これは意図的な設計:JSON は開発者の利便性よりシンプルさと曖昧さのない解析を優先。

JavaScript は別の道を選びました。ES5(2009)は配列リテラルで末尾カンマを明示的に合法とし、ES2017 で関数パラメータにも拡張。JS の末尾カンマは今では一般的スタイル —— リストに新項目を加えた時に git diff が綺麗になるため、多くの linter が要求します。

JavaScript の許可と JSON の許可の間の差が、あなたが見るほぼすべての末尾カンマエラーの根源です。

末尾カンマはどこから来るか

手動編集の設定ファイル

tsconfig.jsonpackage.json、アプリ設定のような設定ファイルは人間が編集します。エントリを追加・削除した後に余計なカンマを残しやすい。多くのエディタ(VS Code、WebStorm)は末尾カンマを許す JSONC(JSON-with-Comments)を黙って受け入れるため、エディタ内では問題なく見えてもランタイムで壊れます。

// "debug": true を消したけどカンマを消し忘れた
{
  "compilerOptions": {
    "strict": true,
    "target": "ES2020",   // ← 今や末尾
  }
}

JavaScript → JSON シリアライズ

開発者は時に JavaScript の値を文字列補間して JSON 文字列を手作りしたり、Array.join(',') を使ったりします。ロジックが各項目の後に無条件でカンマを足すと、最後の項目に末尾カンマが付きます。

// ❌ 素朴な手動シリアライズ
const parts = items.map(item => `"${item.name}": ${item.value}`);
const json = '{' + parts.join(',') + ',}'; // } の前に余計なカンマ

// ✅ JSON.stringify を使う —— 常に妥当な JSON を生成
const json = JSON.stringify(Object.fromEntries(items.map(i => [i.name, i.value])));

LLM と AI の出力

「JSON を出力して」と頼まれた言語モデルは頻繁に末尾カンマを生成します。モデルは訓練中に末尾カンマが合法な膨大な量の JavaScript コードを見ているのでパターンを再現します。AI が生成した JSON は解析前に必ず検証または修復してください。

JavaScript ソースからのコピペ

.js.ts ファイルからオブジェクトリテラルをコピーして JSON コンテキストに貼り付けるのは、末尾カンマが現れる最も一般的な経路の 1 つ。元コードは妥当な JavaScript、貼り付け先は JSON しか受け付けません。

末尾カンマの見つけ方

エラーメッセージは問題に近い位置を指すが、必ずしもカンマそのものではない —— パーサが予期しない }] に当たって初めて何かおかしいと気づく:

SyntaxError: Expected double-quoted property name in JSON at position 58
// または
SyntaxError: Unexpected token '}', ..."score": 98,}" is not valid JSON

報告された位置から逆算します。末尾カンマはエラーを起こした閉じ括弧の直前の文字です。

大きな JSON ファイルでは正規表現検索が助けになります:

// オブジェクト/配列内の末尾カンマを探す
,\s*[}\]]

直し方

オプション 1 —— 手動で削除

問題のオブジェクトや配列の最後の項目を見つけ、その後のカンマを削除。小さなファイルではこれが最速。

オプション 2 —— 正規表現置換(注意)

const fixed = raw.replace(/,\s*([}\]])/g, '$1');
JSON.parse(fixed);

一般的なケースでは動作しますが脆い:,},] をリテラル文字として含む文字列を壊しかねません。そういう文字列が含まれないと分かっている場合のみ使用。

オプション 3 —— ちゃんとした修復パーサを使う

修復パーサは完全な JSON 文法を理解し、文字列内容に触れずに構造的に無効な位置の末尾カンマだけを削除します。プロダクションコードや信頼できない入力では最も安全。

オプション 4 —— 設定ファイルは JSONC に切り替え

末尾カンマが管理下の設定ファイルにあるなら、JSONC(コメント付き JSON)をサポートするパーサへの切り替えを検討。TypeScript の tsconfig.json は既に JSONC。Node.js の設定ファイルなら @humanwhocodes/momoajson5 のようなライブラリが末尾カンマとコメントを許す JSON の上位集合をパースします。

末尾カンマが実際に許される時:JSONC と JSON5

JSON に隣接する 2 つの形式が意図的に末尾カンマ(と他の緩和)を許します。覚えておく価値あり:

  • JSONC(コメント付き JSON) —— tsconfig.json、VS Code の settings.json、その他多くの開発者向け設定で使用。JSONC は // / /* */ コメント 末尾カンマを許可。ファイル名はまだ .json ですが標準 JSON.parse() は拒否 —— VS Code とツール群は JSONC 対応のパーサを同梱。
  • JSON5 —— より広い上位集合:コメント、末尾カンマ、引用符なしキー、一重引用符、複数行文字列、16 進数。json5 npm パッケージや Python の pyjson5 でオプトイン。人間が手編集してパーサを管理できる場面に使う;厳格な JSON を期待するクライアントへ API で送らないこと。

経験則:厳格な JSON パーサを通る全て(API レスポンス、リクエストボディ、ランダムなライブラリが消費するファイル)からは末尾カンマを 排除 し、消費側が認知している JSONC/JSON5 内でのみ受け入れる。

末尾カンマの予防

  • JSON 文字列を手作りしない。 JSON.stringify() を使う —— 常に仕様準拠の出力を生成。
  • linter ルールを追加。 ESLint の jsonc/no-trailing-commas ルールは保存時に .json ファイルの末尾カンマをキャッチ。
  • AI 出力を検証。 言語モデル生成物は使う前に必ず JSON.parse()(または修復パーサ)を通す。
  • Prettier を使う。 Prettier は JSON ファイルを再フォーマットし、保存時に末尾カンマを自動削除。

よくある質問

JSON は末尾カンマを許す?

いいえ。RFC 8259 の JSON 文法はカンマを 2 つの値の間の区切りと厳密に定義しているので、閉じ }] 前に何も無いカンマは無効。すべての標準パーサ —— JSON.parse()、Python の json モジュール、Go の encoding/json —— が拒否します。

JSON から末尾カンマをどう取り除く?

1 つのファイルなら最後の項目の後のカンマを手で削除。繰り返しやプログラム的修正には JSON.stringify() で JSON を再生成、修復パーサ、または JSON Fix のように文字列内容に触れずに構造的末尾カンマを除去するツールを使う。

なぜ JavaScript は末尾カンマを許して JSON は許さないの?

JavaScript は ES5(配列)と ES2017(関数パラメータ)で末尾カンマを開発者利便性機能として追加 —— git diff がきれいになる。JSON は曖昧さのない解析を便利性より優先する意図的にミニマルな交換フォーマットなので、決して採用しなかった。完全な差分は JSON vs JavaScript オブジェクト を参照。

末尾カンマはどんなエラーを起こす?

通常は SyntaxError: Unexpected token '}' または Expected double-quoted property name in JSON、なぜならパーサはカンマの後に別の値を期待し、代わりに閉じ括弧を見つけるから。これは広い JSON.parse「Unexpected token」エラー の一バリアント。

今すぐ直す —— セットアップ不要

末尾カンマ付きの JSON 文字列を今すぐ直したいなら、JSON Fix が他の一般的な問題と一緒に自動で削除 —— 一重引用符、引用符なしキー、Python リテラル、JavaScript コメント。JSON を貼って Repair & Format をクリック、きれいな JSON をコピーバック。アカウント不要、アップロード無し、データはブラウザを出ません。