Skip to content
ブログに戻る
チュートリアル

JSON5 から JSONC まで:より柔軟な JSON フォーマットガイド

JSON5 と JSONC の違いを学び、コメント付き設定ファイルのフォーマットと CI パイプラインへの統合方法を実例コード付きで解説。

9 分で読めます

厳格な JSON のせいで カンマ一つ が原因のデバッグに深夜まで付き合わされた経験はありませんか? そろそろ、もっと寛容な仲間たち — JSON5 と JSON with Comments (JSONC) — に出会うときかもしれません。

JSON5 とは?

JSON5 は ECMAScript 5.1 の機能を取り入れた JSON の拡張で、引用符なしのキー、末尾カンマ、シングルクォート文字列、コメント、16 進数をサポートします。コミュニティによって管理されており、手書きの設定ファイルを厳格な JSON より読みやすく寛容にすることを目的としています。

JSONC とは?

JSONC(JSON with Comments)は、標準 JSON に単一行(//)およびブロック(/* */)コメントを追加した最小限の拡張です。末尾カンマは常に使えるわけではなく、受け付けるかどうかはパーサー次第です。VS Code の設定ファイルや tsconfig.json などの TypeScript 設定ファイルのネイティブフォーマットでもあります。

なぜ「寛容な」JSON が必要なのか

  • 可読性の壁:標準 JSON ではコメント、末尾カンマ、シングルクォートなどが禁止されており、設定ファイルやデモでの意図の伝達が困難です。
  • チーム開発の課題:巨大な JSON ファイルにインラインコメントが一切書けないと、メンテナンスが難しくなり、ちょっとした編集でファイル全体が壊れることも。
  • DevOps の現実:Kubernetes や CI/CD パイプラインでは JSON の動的なマージや生成が日常的。寛容な構文なら手動修正の手間を大幅に削減できます。

JSON5 vs. JSONC 比較表

特徴JSON(RFC 8259)JSONCJSON5
// と /* */ のコメント不可可可
末尾カンマ不可パーサー次第(後述)可(オブジェクト・配列ごとに 1 つ)
クォートなしのキー不可不可可
シングルクォート文字列不可不可可
複数行にまたがる文字列(改行のエスケープ)不可不可可
16 進数(0x1F)不可不可可
.5、5.、先頭の +不可不可可
Infinity、NaN不可不可可
2 進数(0b101)不可不可不可
仕様RFC 8259 / ECMA-404正式な標準なし。事実上 VS Code と jsonc-parser が定義JSON5 仕様 1.0.0
組み込みの JSON.parse / json.loads で読めるか可不可不可

出典:JSON5 仕様、VS Code の JSON ドキュメント、RFC 8259。2 進数の行は実測によるものです。json5 2.2.3 で JSON5.parse('{a: 0b101}') を実行すると、JSON5: invalid character 'b' at 1:6 で失敗します。

一言でまとめると:JSON5 は JavaScript のオブジェクトリテラルに近い書き心地です。JSONC はコメントを許容するだけの普通の JSON で、キーも文字列も従来どおりダブルクォートで囲む必要があります。

JSONC の末尾カンマはパーサー次第

JSONC には公式の仕様がありません。Microsoft が VS Code の設定ファイル向けに非公式に導入し、あわせて jsonc-parser を公開しました。jsonc.org ではコミュニティが仕様草案をまとめて標準化を試みていますが、末尾カンマについては「MAY support trailing commas」(パーサーはサポートしてもよい)としか書かれていません。実際のツールの挙動はまちまちです。

パーサー・ツール末尾カンマ出典
VS Code の JSON with Comments モード受け付けますが、警告が出ますVS Code ドキュメント
jsonc-parser 3.3.1、デフォルトオプションPropertyNameExpected / ValueExpected エラーとして報告されますが、値は返されます後述の実測
jsonc-parser 3.3.1、allowTrailingComma: true受け付けます後述の実測
TypeScript 5.9.3(tsc -p)受け付けます下の tsconfig で実測
Deno(deno.jsonc)受け付けますDeno の設定ドキュメント

どの JSONC パーサーでも読めるファイルにしたいなら、末尾カンマは付けないほうがよいでしょう。

構文の例

標準 JSON(厳格)

{
  "name": "Go Tools",
  "features": ["Base64", "JSON Formatter"]
}

JSON5 の例

JSON5 ファイル config.json5:

// 開発用の設定
{
  name: 'go-tools',
  port: 0x1F90,       // 8080 の 16 進表記
  tags: ['json', 'json5',],
}

JSONC の例

JSONC ファイル tsconfig.json:

{
  // 厳格な型チェック
  "compilerOptions": {
    "strict": true,
    "target": "ES2022", /* モダンな構文で出力 */
  },
  "include": ["src"],
}

そのファイルはどの形式か

拡張子だけでは判断できません。拡張子が .json でも、JSONC や JSON5 としてパースされることがあります。まず下の表を確認し、次にそのファイルを読むツールのドキュメントを確認してください。

ファイル形式補足出典
tsconfig.json、jsconfig.json、tsconfig.*.jsonJSONCVS Code は JSONC モードで開きます。tsc 5.9.3 はコメントと末尾カンマを受け付けますVS Code のソース(typescript-basics)、実測
.vscode/settings.json、tasks.json、launch.jsonJSONCJSON with Comments のファイルとして明記されていますVS Code ドキュメント
devcontainer.jsonJSONC仕様では「a JSON with Comments file」と書かれていますDev Container 仕様
deno.jsoncJSONCドキュメントによれば、deno.jsonc ならコメントと末尾カンマを書けますDeno ドキュメント
babel.config.json、.babelrc.jsonJSON5(拡張子は .json)Babel は JSON5 としてパースします。VS Code は JSONC としてハイライトしますBabel ドキュメント、VS Code のソース
renovate.json5、.renovaterc.json5JSON5renovate.json も JSONC を受け付けますRenovate ドキュメント
その他の *.json5 ファイルJSON5——
package.json厳格な JSONnpm:「It must be actual JSON, not just a JavaScript object literal.」(JavaScript のオブジェクトリテラルではなく、本物の JSON でなければならない)npm ドキュメント、実測

なお、Babel は babel.config.json5 というファイルを探しません。.json5 はドキュメントに記載された拡張子に含まれていないためです。Babel が JSON5 として読むのは、.json で終わる上記の 2 つです。

実際に表示されるエラー(原文のまま)

2 つの小さなファイルを各ランタイムに読み込ませました。comment.json にはコメントが 1 行あります:

{
  // 開発サーバーのポート
  "port": 8080
}

trailing.json には末尾カンマが 1 つあります:

{
  "port": 8080,
}

Node.js 26.10.0 の JSON.parse(Chrome Headless Shell 156 も同じ V8 を使うため、文言はまったく同じ):

comment.json  -> SyntaxError: Expected property name or '}' in JSON at position 4 (line 2 column 3)
trailing.json -> SyntaxError: Expected double-quoted property name in JSON at position 18 (line 3 column 1)

Python 3.13.5 の json.loads:

comment.json  -> json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
trailing.json -> json.decoder.JSONDecodeError: Illegal trailing comma before end of object: line 2 column 15 (char 16)

jq 1.7:

comment.json  -> jq: parse error: Invalid numeric literal at line 2, column 5
trailing.json -> jq: parse error: Expected another key-value pair at line 3, column 1

npm 11.19.1(package.json に // comment という行を入れた場合):

npm error code EJSONPARSE
npm error JSON.parse Invalid package.json: JSONParseError: Expected property name or '}' in JSON at position 4 (line 2 column 3) while parsing near "{\n  // comment\n  \"name\":..."
npm error JSON.parse Failed to parse JSON data.
npm error JSON.parse Note: package.json must be actual JSON, not just JavaScript.

エラーの読み方:

  • position 4 (line 2 column 3) はコメントの最初の / を指しています。 エラー位置が // や /* で始まる行の先頭にあれば、そのファイルはほぼ確実に JSONC か JSON5 です。
  • 末尾カンマでは、V8 と Python が指す位置が異なります。 V8 は閉じ括弧の }(3 行目)を、Python 3.13.5 はカンマそのもの(2 行目 15 列)を報告します。ほかのバージョンでは文言が異なる場合があります。上のテキストは、これらのバージョンが実際に出力したとおりのものです。
  • エラーが見えない文字を引用している場合、たとえば Node 26 の Unexpected token '', "{}" is not valid JSON(2 つのクォートの中には、実際には目に見えない U+FEFF が入っている)のようなときは、コメントではなく、ファイル先頭にある不可視のバイトオーダーマーク(BOM)が原因である可能性が高いでしょう。詳しくはUTF-8 BOM で JSON.parse が失敗する原因と削除方法を参照してください。

JSONC・JSON5 を標準 JSON に変換する

変換するとコメントはすべて消えます。JSON にはコメントを保持する場所がないためです。コメント付きのファイルをソースとして残し、出力した .json は生成物として扱うとよいでしょう。

Node.js:json5 で JSON5 を JSON に変換する

// json5-to-json.mjs(事前に npm install json5 を実行)
import { readFileSync, writeFileSync } from 'node:fs';
import JSON5 from 'json5';

const data = JSON5.parse(readFileSync('config.json5', 'utf8'));
writeFileSync('config.json', JSON.stringify(data, null, 2) + '\n');

json5 2.2.3 で上の JSON5 の例を処理すると、config.json は次のようになります:

{
  "name": "go-tools",
  "port": 8080,
  "tags": [
    "json",
    "json5"
  ]
}

Node.js:jsonc-parser で JSONC を JSON に変換する

jsonc-parser は Microsoft による JSON with Comments 用のパーサーです。その parse() は構文エラーがあっても例外を投げません。問題は errors 配列に集められ、それでも可能な範囲で値が返されます。そのため、この配列は自分でチェックする必要があります:

// jsonc-to-json.mjs(事前に npm install jsonc-parser を実行)
import { readFileSync } from 'node:fs';
import { parse, printParseErrorCode } from 'jsonc-parser';

const errors = [];
const data = parse(readFileSync('tsconfig.json', 'utf8'), errors, {
  allowTrailingComma: true,
});
if (errors.length > 0) {
  for (const e of errors) console.error(printParseErrorCode(e.error), 'at offset', e.offset);
  process.exit(1);
}
console.log(JSON.stringify(data, null, 2));

jsonc-parser 3.3.1 で上の tsconfig の例を処理すると、きれいな JSON が出力され、終了コード 0 で終わります。allowTrailingComma: true を外すと、同じファイルでは、各末尾カンマの直後にある } の位置で PropertyNameExpected と ValueExpected が報告されます。

Python:json5 パッケージ

標準ライブラリの json モジュールには、コメントを許可するオプションがありません。json5 パッケージは JSON5 を読めるので、JSONC も読めます。コメントも末尾カンマも、JSON5 では正しい構文だからです:

# 事前に pip install json5 を実行
import json

import json5

with open("tsconfig.json", encoding="utf-8") as f:
    data = json5.load(f)

print(json.dumps(data, indent=2, ensure_ascii=False))

Python 3.13.5 と json5 0.17.3 で試したところ、Node 版と同じ JSON が出力されました。

コマンドライン:json5 CLI

npm の json5 パッケージには、JSON への変換と検証ができる CLI が付属しています。JSONC ファイルも読めます:

npx json5 config.json5                      # 圧縮した JSON を標準出力へ
npx json5 -s 2 -o config.json config.json5  # インデントを付けてファイルに書き出す
npx json5 -v tsconfig.json                  # 検証のみ。構文エラーなら終了コード 1

-v は構文エラーがあると終了コード 1 で終了するため、同じコマンドを CI のステップとして使えば、手で編集した JSON5 や JSONC のファイルをチェックできます。

ここで jq は役に立ちません。前述のとおり、jq 1.7 は最初のコメントで止まってしまいます。

Infinity と NaN に注意

JSON5 では Infinity と NaN を書けますが、JSON にはこれらを表す方法がありません。しかも、その扱いは言語によって異なります:

JSON.stringify(JSON5.parse('{a: Infinity, b: NaN}'));
// '{"a":null,"b":null}'(何の警告もなく null になる)
json.dumps(json5.loads('{a: Infinity, b: NaN}'))
# '{"a": Infinity, "b": NaN}'(JSON として正しくない出力)
json.dumps(json5.loads('{a: Infinity}'), allow_nan=False)
# ValueError: Out of range float values are not JSON compliant: inf

JSON5 ファイルにこれらの値が含まれうるなら、Python では allow_nan=False を渡すか、変換前にチェックしてください。また、" やバックスラッシュを含むシングルクォートの JSON5 文字列は、JSON.stringify によってエスケープし直されます。そのルールはJSON文字列のエスケープ完全ガイドにまとめています。

変換した JSON を検証する

変換が終わったら、出力を JSON フォーマッターに貼り付けて検証・整形するとよいでしょう。処理はブラウザ内で完結します。

ただし、このフォーマッターが受け付けるのは厳格な JSON だけです。ブラウザの JSON.parse でパースするため、JSONC や JSON5 のファイルをそのまま貼り付けると構文エラーになり、パースが止まった行と列が表示されます。先に変換し、それから検証してください。

JSONC や JSON5 を使うべきでない場面

  • API のペイロードとデータ交換。 RFC 8259 は、JSON を生成する側が「MUST strictly conform to the JSON grammar」(JSON の文法に厳密に従わなければならない)と定めています。受け取る側はたいてい JSON.parse か json.loads で、どちらもコメントを拒否します。
  • package.json。 npm は厳格な JSON を要求します。コメントが 1 つあるだけで、npm run などの npm コマンドが EJSONPARSE で失敗します。
  • 自分が管理していないツールが読むファイル。 Node の require('./tsconfig.json') は厳格な JSON パーサーを使うため、コメント付きの tsconfig では失敗します(SyntaxError: …tsconfig.json: Expected property name or '}' in JSON at position 4)。JSONC ファイルを読むスクリプトには、JSONC パーサーが必要です。
  • いつの間にか JSONC になっていた .json ファイル。 Renovate のドキュメントは、コメント入りの .json ファイルより .jsonc ファイルを推奨しています。前者は「can cause issues with editors and syntax highlighting」(エディターやシンタックスハイライトで問題を起こしうる)からです。拡張子で形式を明示すれば、どのツールにも何を読めばよいかが伝わります。

設定ファイルの形式をゼロから選び、どこでもコメントを書きたいなら、TOML と YAML はネイティブでコメントに対応しています。比較はTOML vs JSON vs YAML:設定ファイル形式はどれを選ぶ?を参照してください。

実践的なヒントと注意点

1. 本番環境にデプロイする前に変換する

  • ブラウザの JSON.parse は依然として厳格な JSON しか受け付けません。
  • ビルド時に、上の変換セクションで紹介した方法で厳格な JSON に変換しておきましょう。

2. セキュリティと信頼性

  • 寛容な構文は不正なフィールドを見逃すリスクがあります。API をリリースする前に JSON Schema や zod で必ずバリデーションしましょう。

3. チームの規約を定める

  • README やコントリビューションガイドで「*.json5 は設定ファイル専用、リリースパッケージは厳格な .json を使う」と明記します。
  • Prettier のルールを統一して、フォーマットの違いによる無意味な diff を防ぎましょう。

4. パフォーマンス

  • JSON5/JSONC のパースには追加の依存関係とわずかなオーバーヘッドが発生します。CLI や開発ツールでは問題ありませんが、本番環境では計測を行いましょう。

よくある質問

JSON5 と JSONC の違いは何ですか?

JSONC は標準 JSON に // と /* */ のコメントを加えたもので、末尾カンマを使えるかどうかはパーサー次第です。JSON5 はさらに踏み込み、ES5.1 の構文を取り入れています:クォートなしのキー、シングルクォート文字列、16 進数、Infinity/NaN、末尾カンマ。有効な JSONC ファイルはたいてい有効な JSON5 でもありますが、その逆は成り立ちません。コメントだけで十分なら JSONC を、より豊富な構文が必要なら JSON5 を選びましょう。

JSON5 や JSONC を本番 API で使用できますか?

いいえ——JSON5 と JSONC は設定ファイル向けに設計されており、データ交換には適していません。API では最大限の相互運用性のために標準 JSON(RFC 8259)を使用すべきです。JSON5/JSONC は tsconfig.json、.vscode/settings.json などのローカル設定ファイルに限定し、機械的なパースより人間の可読性が重要な場面で使いましょう。

VS Code は JSON5 をネイティブサポートしていますか?

標準の状態ではサポートしていません。VS Code に組み込まれた JSON 拡張機能が登録している言語には json、jsonc、jsonl などがありますが、json5 は含まれません。そのため .json5 ファイルのシンタックスハイライトには、マーケットプレイスの拡張機能が必要になります。一方、JSONC は組み込みでサポートされており、設定ファイル、tasks.json、launch.json、tsconfig.json はいずれも JSON with Comments モードで開かれます。

JSON5 を標準 JSON に変換するにはどうすればよいですか?

json5 npm パッケージを使います。JSON5.parse() で JSON5 を読み込み、JSON.stringify() で標準 JSON を出力します。CLI では npx json5 < input.json5 > output.json を実行します。変換するとコメントは削除され、Infinity と NaN は JSON.stringify によって null になる点に注意してください。Go Tools の JSON フォーマッターなどのオンラインツールでも、変換後の出力を検証して正確性を確認できます。

JSONC は JSON with Comments と同じものですか?

はい。「JSON with Comments」は VS Code の言語モードの名前で、jsonc はその言語 ID であり、ファイル拡張子でもあります。VS Code、TypeScript(tsconfig.json)、その他の Microsoft ツールが使用しています。正式な標準はなく、jsonc.org では jsonc-parser がデフォルトで受け付ける内容をもとにしたコミュニティ草案が公開されています。// と /* */ のコメントは書けますが、末尾カンマを受け付けるかどうかはパーサーによって異なります。

Base64 エンコーディング、ハッシュ生成、タイムスタンプ変換など、ブラウザベースの開発者ツールについては開発者必携ツールガイドをご覧ください。

まとめ

可読性と厳密性のバランスを取ることは、開発者にとって永遠のテーマです。JSON5 と JSONC は記述体験を大幅に改善してくれます。適切なビルドパイプラインとバリデーション機構を組み合わせれば、「寛容な JSON」のメリットを安全に享受できます。

参考リンク

タグ: json json5 jsonc formatting developer-tools