JSON の末尾カンマ — 先に結論
末尾カンマとは、オブジェクトや配列の最後の要素のあと、閉じ括弧 } や ] の直前に残ったカンマのことです。標準 JSON(RFC 8259)はこれを許可していないため、厳密なパーサーは Unexpected token } や Expecting property name enclosed in double quotes といったエラーでファイルを拒否します。直し方は、その 1 つのカンマを消すだけです。
このページが扱うのは末尾カンマ(,)の話で、// や /* */ のコメントの話ではありません。JSON にコメントを書きたい場合は別の話題で、JSON にコメントは書けるか にまとめています。ここでは余分なカンマに絞って、なぜエラーになるのか、どう見つけるか、どう消すか、そして JSON5 / JSONC では何が違うのかを解説します。
ブラウザでその場で直す
エラーをすぐ消したいだけなら、文字数を手で数える必要はありません。
- JSON Formatter を開きます
- 失敗している JSON を貼り付けます
- 表示されたエラー行を読みます。余分なカンマの直後にある閉じ括弧を指しています
- その
}や]の直前のカンマを削除して、もう一度 Run を押します - 整形済みの正しい JSON を出力からコピーします
整形はすべてブラウザ内で動きます。貼り付けた JSON はアップロードも記録も保存もされません。API レスポンスや社内データを含む設定ファイルを扱うときに、この点が効いてきます。


修正前と修正後
末尾カンマが現れる場所は 3 通りです。それぞれ壊れた例と修正後を並べます。
オブジェクトの末尾カンマ:
{
"name": "Aoi",
"role": "Engineer",
}
{
"name": "Aoi",
"role": "Engineer"
}
配列の末尾カンマ:
[
"red",
"green",
"blue",
]
[
"red",
"green",
"blue"
]
ネスト — 内側のオブジェクトや配列に末尾カンマが隠れていることもあります:
{
"tags": ["a", "b",],
"meta": {
"active": true,
}
}
{
"tags": ["a", "b"],
"meta": {
"active": true
}
}
どの場合も直し方は同じで、最後の値と閉じ括弧のあいだにあるカンマを消すだけです。値そのものには問題ありません。
出てくるエラーメッセージ
同じ末尾カンマでも、どの言語で読むかによってパーサーの言い回しが変わります。
ブラウザ・Node.js(V8)の JSON.parse:
SyntaxError: Unexpected token } in JSON at position 42
SyntaxError: Expected double-quoted property name in JSON at position 42
Python の json.loads:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 4 column 1 (char 42)
共通しているのはパーサーがカンマまで進み、その次にもう 1 つの値かキーを期待したのに代わりに閉じ括弧が来た、という点です。多くのパーサーでは、報告される position や行番号は閉じ括弧 } / ] の位置なので、削除すべきカンマはその 1 つ前の行にあります(ただし Python は例外で、後述のとおりカンマ自体の位置を指します)。
同じ入力を 5 つのパーサーに実際に通すと位置の指し方がどれだけ割れるかが分かります(実測: scripts/benchmarks/json-trailing-comma/、2026-08-17、Node.js v26.7.0 / Python 3.14.6 / jq 1.7.1-apple / json5 2.2.3 / jsonc-parser 3.3.1)。入力はこの複数行オブジェクトです。
{
"a": 1,
"b": 2,
}
| パーサー | 末尾カンマをどう扱うか |
|---|---|
V8 (Node.js) JSON.parse | 受理しない。Expected double-quoted property name in JSON at position 22 (line 4 column 1) |
Python json.loads | 受理しない。Illegal trailing comma before end of object: line 3 column 9 (char 20) |
| jq | 受理しない。jq: parse error: Expected another key-value pair at line 4, column 1 |
| JSON5 | 受理する(エラーなし) |
| jsonc-parser | 受理しない。PropertyNameExpected at offset 22; ValueExpected at offset 22 |
位置の指し方はパーサーで割れます。V8 と jsonc-parser は閉じ括弧の位置(offset 22 / line 4 column 1)を指し、jq は閉じ括弧のある行を指しますが、Python だけはカンマ自体の位置(line 3 column 9)を指します。
メッセージは出るのにカンマが見つからないときは、JSON Formatter に貼り付ければ該当行を示してくれます。シングルクォート・キーのクォート漏れ・カンマ不足など、パースエラー全般の原因一覧は JSON Parse Error の解決方法 にまとまっています。
なぜ JSON は末尾カンマを禁止するのか
RFC 8259別タブで開きます では、カンマは値と値を区切る separator(区切り)であって、各値のあとに付ける terminator(終端記号)ではありません。Section 2 の文法は、配列を「カンマで区切られた値の並び」、オブジェクトを「カンマで区切られたメンバーの並び」と定義しており、最後の値のあとに要素を置く production rule が存在しません。そのため、空白と閉じ括弧しか続かないカンマは区切る対象がなく、仕様準拠のパーサーは拒否します。
このミスが多いのも同じ理由です。JavaScript のオブジェクトリテラルや配列リテラルでは末尾カンマが許され、多くのエディタが .js ファイルをその形で整形します。しかし JSON.parse() が読むのは JavaScript ではなく厳密な JSON です。.js ファイルの中なら問題なく動くテキストでも、JSON としてパースした瞬間に失敗します。コードからオブジェクトを .json ファイルにコピーするのが、末尾カンマが紛れ込む典型的な経路です。
厳密な JSON の残りのルールは JSON の書き方ガイド を参照してください。
末尾カンマを自動で取り除く
1 つのカンマを手で消すのは一瞬ですが、JSON を生成する場面や多数のファイルを直す場面では自動化します。
文字列連結ではなくシリアライザで生成します。JSON.stringify(および各言語の同等機能)は末尾カンマを出力しないため、そもそも問題が起きません。
const data = { name: "Aoi", role: "Engineer" };
const json = JSON.stringify(data, null, 2);
// 常に正しい — 末尾カンマは決して出力されない
保存時に整形します。VS Code で .json ファイルに Format Document(または Prettier の format-on-save)をかけると、再整形の一環として末尾カンマが取り除かれます。手で編集する設定ファイルを綺麗に保つ、いちばん手軽な方法です。
正規表現は最終手段です。,\s*([}\]]) は「カンマ + 空白 + 閉じ括弧」にマッチします。
const cleaned = source.replace(/,(\s*[}\]])/g, "$1");
const data = JSON.parse(cleaned);
これはあくまでフォールバックとして扱ってください。文字列値の中にあるカンマ(例: "a,}")に誤爆することがあるため、自分で管理しているファイルにのみ使い、処理後は JSON Formatter で結果を検証してください。
パーサーのオプションは「受け入れる」だけで「書き換える」わけではありません。末尾カンマを許容できるライブラリもあります(.NET の JsonSerializerOptions.AllowTrailingCommas など)。これらは自分のコードがファイルを読めるようにするだけで、ディスク上のファイルを変えたり、別の厳密なパーサーで有効にしたりはしません。JSON を別サービスに送る必要があるなら、結局カンマを削除する必要があります。
Python で一括除去する
標準ライブラリの json は末尾カンマを受け付けませんが、json5 パッケージなら JSON5 仕様(末尾カンマ許可)としてパースできます。パーサー経由なので、正規表現と違って文字列値の中の ,} を誤って壊しません。
# pip install json5
import json, json5
with open("broken.json") as f:
data = json5.load(f)
with open("fixed.json", "w") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
Node.js で一括除去する
npm の json5 パッケージで読み込み、標準の JSON.stringify で書き出し直します。
// npm install json5
import JSON5 from "json5";
import fs from "node:fs";
const data = JSON5.parse(fs.readFileSync("broken.json", "utf8"));
fs.writeFileSync("fixed.json", JSON.stringify(data, null, 2));
sed で複数ファイルを一括処理する
CI やシェルスクリプトから多数のファイルをまとめて直す場合は sed が手軽です。ただし前述の正規表現と同じ誤爆リスクがあるため、処理後のパース検証を必ず入れてください。
sed -E 's/,[[:space:]]*([}\]])/\1/g' broken.json > fixed.json
python3 -c "import json; json.load(open('fixed.json'))" # 検証
jq では直せない点に注意
jq のパーサーは厳密で、末尾カンマを含む入力そのものを受け付けません。jq . broken.json は修復ではなくエラーで停止します。jq は「正しい JSON の変形・抽出」のためのツールなので、除去には上記のいずれかを使い、直った後の加工に jq を使ってください。
末尾カンマを再発させない
一度直しても次のファイルで再発するのを防げるわけではありません。早めに捕まえるためのガードがいくつかあります。
- エディタ: VS Code は
.jsonファイルの末尾カンマを警告します(.jsoncでは警告しません)。拡張子を.jsonのままにして警告を有効に保ちます - 起きやすい場所を知る: 末尾カンマは、手で編集した設定ファイル、
.jsのソースからコピーした JSON、文字列連結で組み立てた JSON で最も多く出ます。本物のシリアライザで生成した JSON は安全です
trailingComma はどこから来るのか
保存時の自動整形が、末尾カンマが戻ってくる原因になることがあります。Prettier 本体のドキュメントと issue tracker に書かれている内容は次のとおりです。
| 項目 | 内容 | 出典 |
|---|---|---|
| Prettier の既定値 | trailingComma の既定値は v3.0.0 以降 "all"。それ以前は "es5" だった | prettier.io/docs/options別タブで開きます |
| VS Code 拡張 | trailingComma を強制的に無効化しているのは Prettier 本体ではなく VS Code 拡張自体で、パーサーが json のときだけ効く — 変更要望の issue は closed かつ locked | prettier-vscode#589別タブで開きます |
tsconfig.json | 拡張子が .json でも、Prettier 本体はこのファイルを JSONC と推定するため、保存すると末尾カンマが付くことがある — closed as not planned | prettier#15942別タブで開きます |
.jsonc 全般 | 同じ JSONC 推定が .jsonc 拡張子のファイル全般にも起きる — issue は needs discussion のまま open | prettier#15956別タブで開きます |
CI に JSON.parse のゲートを置く
JSON 対応の linter や、ビルド中の JSON.parse ステップは、末尾カンマが下流のサービスで問題を起こす前に食い止めます。依存ライブラリなしの最小構成は次のとおりです。
node -e "JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'))" config.json
これを pre-commit フックにするか、CI でリポジトリ内の .json ファイル全体にループさせます。手で編集する設定ファイルには特に入れる価値があります。末尾カンマが再発しやすいのはまさにそうしたファイルだからです。
JSON5 / JSONC では末尾カンマが許される
差分を綺麗にするためなどで、どうしても末尾カンマを使いたい場合は、それを許可するフォーマットがあります。
- JSON5 は正式な仕様を持つ JSON のスーパーセットで、末尾カンマ・コメント・キーのクォート省略・シングルクォートを無条件に許可します(実測した 5 パーサー中で唯一
accepted: true、例外もエラーも出ません。scripts/benchmarks/json-trailing-comma/) - JSONC(VS Code が使う「コメント付き JSON」)はコメントを追加します。VS Code が使う
jsonc-parserはエラー回復(lenient recovery)を行う実装で、末尾カンマがあっても例外を投げず値は返しますが、その末尾カンマはerrors配列にエラーとして記録されます(上表のjsonc-parser行)。値が返ってくることと仕様上受理されることは別の話で、VS Code の設定ファイルが末尾カンマを許すように見えるのは前者の挙動です
注意点は通用範囲です。これらを理解するツールが読む設定ファイルなら問題ありませんが、API のペイロード、package.json、厳密な JSON.parse を使うサービスでは有効になりません。RFC 8259 Section 9 がこうした拡張をどう認めているかを含む詳しい比較は、コメントの観点から同じスーパーセットを扱う JSON にコメントは書けるか にあります。
目的が「読みやすい厳密な JSON」であれば、結果を JSON Formatter に通し、大きなペイロードを整える具体的なコツは JSON 整形のコツと注意点 を参照してください。
よくある質問
JSON で末尾カンマは使えますか?
使えません。RFC 8259 はカンマを値と値の区切りと定義しており、最後の値のあとに要素を置くことを許していません。そのため閉じ括弧 } / ] の直前のカンマは無効で、厳密なパーサーは Unexpected token } のようなエラーで拒否します。
末尾カンマはどうやって見つけて消しますか?
JSON Formatter に JSON を貼り付けてください。エラーメッセージが、余分なカンマの直後にある閉じ括弧を指すので、その 1 つ前の行にあるカンマを消してもう一度実行します。再発を防ぐには、文字列を手で組み立てず JSON.stringify で生成します。
なぜ JavaScript では末尾カンマが使えて JSON では使えないのですか?
JavaScript のオブジェクト・配列リテラルは利便性として末尾カンマを許します。JSON は JSON.parse が読む厳密なデータフォーマットで、RFC 8259 に従い、最後の値のあとに要素を置くルールがありません。同じテキストが JS リテラルとしては有効で、JSON としては無効になります。
末尾カンマはどんなエラーメッセージになりますか?
多くは V8 / Node で Unexpected token }(または ])、新しい V8 で Expected double-quoted property name、Python で Expecting property name enclosed in double quotes です。いずれも、別の値かキーを期待した位置に閉じ括弧が来た、という意味です。
削除せずに末尾カンマを許可するだけではだめですか?
許容するよう設定できるパーサーもあります(.NET の AllowTrailingCommas など)。ただしそれはファイルを読む側のコードを助けるだけで、別のパーサーや送信のためにファイルを有効にするわけではありません。相互運用できる JSON にするには、カンマを削除します。
JSON5 では末尾カンマは動きますか?
動きます。JSON5 は末尾カンマを明示的に許可し、コメントやキーのクォート省略も認めます。ローカルの設定ファイルには向いていますが、厳密な RFC 8259 JSON が必要な API データには使えません。
まとめ
- 末尾カンマは閉じ括弧
}/]の直前のカンマで、標準 JSON はこれを禁止します - エラーは
Unexpected token }やExpecting property name enclosed in double quotesの形で出ます。報告される位置は括弧なので、カンマはその 1 つ前にあります - 最速の直し方は、JSON Formatter にファイルを貼り、行を読んでカンマを消すことです
JSON.stringifyで生成し、保存時に整形すれば末尾カンマの再発を防げます- JSON5 / JSONC は末尾カンマを許可しますが、それを理解するツール向けであり、API のペイロードには使えません