JSON パースと処理ライブラリの比較
要点:ネイティブ API は最速で、寛容なパーサーはオフセットを返します。エラー位置、元のテキストを保つか、境界が明示されているかの三点で選びます。

要点:まずニーズを分類し、それから実装を比べましょう。読み取り専用の値にはネイティブ JSON.parse、オフセットが必要か元の整形を保たなければならないなら jsonc-parser、クエリやパッチのライブラリは必要な箇所にだけ足します。大きなライブラリはページごとに遅延読み込みし、保守されていないものは外します。
どのライブラリも「速く、小さく、完全」と主張します。本当に差を付けるのは、何かが壊れたときにどれだけの情報をくれるかです。
1. 目的別の四つのカテゴリ
| カテゴリ | 代表的なライブラリ | 解決するもの |
|---|---|---|
| 標準パース | JSON.parse / JSON.stringify |
構文 ↔ オブジェクト。速度優先 |
| 寛容なパース + 編集 | jsonc-parser、json5 |
コメント付き入力、オフセットまで正確なエラー、整形を保つ変更 |
| クエリ | jsonpath-plus、jsonpath |
式でノードを選択 |
| 変更 | fast-json-patch、immer |
パッチの生成/適用、不変更新 |
まずどのカテゴリにいるかを特定し、それから具体的な実装を比べます。さもないとクエリライブラリでパーサーの仕事をしがちです。
2. 並列比較
| ライブラリ | エラー位置 | 寛容さ(コメント/末尾カンマ) | 元の整形を保つ | 適する場面 |
|---|---|---|---|---|
JSON.parse |
メッセージと位置のみ(エンジン依存) | ✗ | ✗ | 既定のパース、API データ |
jsonc-parser |
正確な offset + エラーコード |
✓ | ✓(modify + applyEdits) |
エディタ、設定ファイル |
json5 |
行と列の情報 | ✓(より寛容) | ✗ | JSON5 設定の読み取り |
jsonlint |
行と列の情報 | ✗ | ✗ | 参考のみ。活発に保守されていない |
jsonpath-plus |
式の構文エラー | — | — | 式によるクエリ |
fast-json-patch |
操作レベルのエラー | — | — | パッチの生成と適用 |
lz-string |
— | — | — | JSON を URL に圧縮 |
JSON.parse のエラーメッセージはエンジン間で大きく異なります。V8 は
Unexpected token } in JSON at position 42 のようなものを出しますが、位置が正確かはエンジンのバージョンに依存します。
jsonc-parser は代わりに安定した構造化された { error, offset, length } を返し、エディタのマーカーに適します。
3. 四つの重要な判断点
3.1 オフセットが必要か
エディタを作り、「エラーをクリックして該当行へジャンプ」したいなら、オフセットが必須です。テストは単純です。 エラーメッセージが「不正な JSON」としか出せないなら、ユーザーは自分で探さなければなりません。
import { parse, printParseErrorCode } from 'jsonc-parser';
const errors: Array<{ error: number; offset: number; length: number }> = [];
parse(text, errors, { allowTrailingComma: true, disallowComments: false });
if (errors.length > 0) {
const firstError = errors[0];
console.error(`${printParseErrorCode(firstError.error)} at offset ${firstError.offset}`);
}
3.2 元のテキストを保つ必要があるか
値を読むだけ → どのパーサーでもよい。 「一つのフィールドを変え、他はすべてそのまま」 → 「パース → オブジェクト変更 → シリアライズ」ではなく編集スタイルの API を使わなければなりません。
後者は次を失います。コメント、キー順(一部の実装)、インデントスタイル、数値リテラルの表記(1e3 が 1000 になる)、エスケープ形式(\u4e2d が実際の文字になる)。
3.3 境界の振る舞いが明示されているか
ライブラリを選ぶ前に、ドキュメントで三つを確認します。
- 重複キーの扱い(最後を残す / エラー)。
- 大きな整数が精度を失うか(ほとんどの JS ライブラリは
Numberを通すので失う)。 - BOM、コメント、末尾カンマの対応範囲。
ドキュメントがなければ、小さなサンプルを書いて自分で試してください。README を読むより信頼できます。
3.4 保守状況
JSON ライブラリのリスクは機能不足ではなく、長期的な放置です。セキュリティパッチ(プロトタイプ汚染、ReDoS)を出してくれる人がいなくなります。
4. 他言語との比較
| 言語 | 標準/主要ライブラリ | 主な違い |
|---|---|---|
| JavaScript | JSON.parse |
すべての数値が倍精度 |
| TypeScript | 同上 + jsonc-parser / zod |
型はコンパイル時のみ |
| Go | encoding/json |
既定は float64。精度を保つには UseNumber()。遅延パースには json.RawMessage |
| Java | Jackson / Gson / Moshi | Jackson では既定の型付けを有効にするリスクに注意 |
| Python | json / orjson |
parse_float=Decimal で精度を保つ。orjson は速いが全型非対応 |
| Rust | serde_json |
強い型付けのデシリアライズ。arbitrary_precision 機能で精度を保つ |
| C++ | simdjson / RapidJSON | simdjson はパーススループット重視、RapidJSON はより汎用 |
言語をまたいでデータを交換するとき、最もつまずきやすいのは依然として数値精度と時刻形式です。ライブラリの選択は緩和できても、除去はできません。
5. 典型的な組み合わせ
構成 1:ツールサイト(ブラウザ側)
パースとエラー位置:jsonc-parser
エディタ:CodeMirror 6 + @codemirror/lang-json
クエリ:jsonpath-plus
パッチ:fast-json-patch
共有リンク:lz-string
この組み合わせの特徴は、すべてがローカルで動き、データをアップロードしないことです。ユーティリティサイトのプライバシー期待に合います。
構成 2:サーバー側 API ゲートウェイ
検証:Ajv(スキーマを一度コンパイルして再利用)
パース:ネイティブ JSON.parse(ボディサイズ制限と一緒に)
大きなフィールドの遅延パース:生の文字列を保ち、必要時にだけパース
ゲートウェイ層にクエリ/パッチライブラリを持ち込んで業務ロジックを実装しないでください。それは業務層の仕事です。
構成 3:CLI とスクリプト
フィールド選択:jq
形式変換:yq / dasel
インタラクティブ閲覧:jless
一括検証:ajv-cli
6. バンドルサイズと性能の実際の影響
jsonc-parserは非常に小さく、メインバンドルに適します。json5はより多くの構文を支えるためjsonc-parserよりやや大きいです。jsonpath-plusは式評価を含み明らかに大きいので、ページごとに遅延読み込みすべきです。fast-json-patchは中程度で、比較機能があるときにだけ必要です。
最適化は単純です。ページごとに動的インポートし、ファーストスクリーンのチャンクに入れないこと。
const { JSONPath } = await import('jsonpath-plus');
7. チェックリスト
- [ ] 目的でライブラリを選ぶ。パースにクエリライブラリを使わない。
- [ ] 正確なエラー位置が必要なら
jsonc-parserを使う。 - [ ] コメントと整形を保つ必要があるなら編集スタイルの API を使う。
- [ ] 三つの境界振る舞い(重複キー、大きな整数、BOM)を実際に試す。
- [ ] ライブラリの保守状況とセキュリティ勧告を監視する。
- [ ] 大きなライブラリはオンデマンドで動的インポートする。
FAQ
プロジェクトの規模に応じて JSON ライブラリをどう選べばよいですか?
API データを読むだけの小さなツールはネイティブ JSON.parse のままでよいです。エディタ品質のエラー位置が必要か、元の整形を保たなければならないプロジェクトは jsonc-parser を使います。サーバー側ゲートウェイは検証とパースだけを必要とし、クエリとパッチのライブラリは業務層に任せます。CLI スクリプトは jq、yq、ajv-cli を直接使えます。
機能数より保守状況が重要なのはなぜですか?
JSON ライブラリの本当のリスクは機能不足ではなく長期的な放置です。プロトタイプ汚染や ReDoS のセキュリティパッチを出してくれる人がいなくなります。機能一覧がどれほど完全でも、止まったライブラリは自分でパッチを当てることになります。機能表を比べるのではなく、保守とセキュリティ勧告を厳格な基準にしてください。
一つのフィールドを変え、コメントとインデントを保つのに JSON.parse を使うべきですか?
いいえ。パースしてオブジェクトを変更してシリアライズすると、コメント、キー順、インデントスタイル、数値リテラルの表記(1e3 が 1000 になる)、エスケープ形式(\u4e2d が実際の文字になる)を失います。一つのフィールドだけを変え、他をそのまま保つには、jsonc-parser の modify と applyEdits のような編集スタイルの API が必要です。