# 機能設計書 11-JSON/JSON5/JSONC パース

## 概要

本ドキュメントは、Prettierにおける JSON、JSON5、JSONC（コメント付きJSON）ファイルのパース機能について記述する。

### 本機能の処理概要

**業務上の目的・背景**：JSONはWebアプリケーション開発における設定ファイル、API通信、データ交換において最も広く使用されるデータフォーマットである。プロジェクトごとにpackage.json、tsconfig.json、各種設定ファイルが存在し、これらのフォーマットを統一することでチーム開発における可読性向上とコードレビューの効率化を実現する。JSON5やJSONCはコメントを許容するため、設定ファイルの説明を記述できる拡張仕様として利用される。

**機能の利用シーン**：
- package.jsonやpackage-lock.jsonのフォーマット時
- tsconfig.json（JSONC形式）の編集時
- JSON5形式の設定ファイル（例：.babelrc.json5）の処理時
- API レスポンスやモックデータのJSON整形時

**主要な処理内容**：
1. Babel パーサーを使用してJSONテキストを抽象構文木（AST）にパース
2. JSON仕様に準拠したノードの検証（不正なノードタイプの検出）
3. JSON5特有の構文（コメント、末尾カンマ、Infinity/NaN等）のサポート
4. JSONC（VS Code互換）形式でのコメント許容と空ファイル対応
5. json-stringify パーサーによるpackage.json等の特殊ファイル処理

**関連システム・外部連携**：
- Babel パーサー（@babel/parser）を内部的に使用
- linguist-languages による言語定義の取得
- VS Codeとの互換性（vscodeLanguageIds: "json", "jsonc", "json5"）

**権限による制御**：なし（全ユーザーが利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Playground | API連携 | JSON、JSON5、JSONCをパース |
| 5 | About - Prettier概要 | 補助機能 | 対応言語としてJSONパースを説明 |

## 機能種別

パース処理（テキストからAST変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | string | Yes | パース対象のJSONテキスト | 空文字列の場合はJSONCパーサーのみ許容 |
| options | object | No | パースオプション | - |
| options.allowComments | boolean | No | コメントを許可するか（デフォルト: true） | - |
| options.allowEmpty | boolean | No | 空ファイルを許可するか（デフォルト: false） | - |

### 入力データソース

- ファイルシステムからのJSON/JSON5/JSONCファイル読み込み
- エディタからのテキスト入力（API経由）
- 標準入力からのJSONテキスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ast | JsonRoot | パース結果のAST。type="JsonRoot"で、expressionプロパティに実際のJSONデータノードを含む |
| ast.expression | Node | ObjectExpression、ArrayExpression、リテラルノード等 |
| ast.comments | Array | コメントノードの配列（JSON5/JSONC時） |

### 出力先

- Prettier内部のフォーマット処理パイプライン
- デバッグAPI（__debug.parse）経由でのAST出力

## 処理フロー

### 処理シーケンス

```
1. parseJson関数がテキストを受け取る
   └─ オプション（allowComments, allowEmpty）の設定確認
2. Babel parseExpressionでJSONテキストをパース
   └─ パースエラー発生時はcreateBabelParseErrorで変換
3. 空ファイルの場合はparseEmptyJsonで処理
   └─ ディレクティブなし、本体なしを確認
4. コメント禁止設定時のコメント存在チェック
   └─ コメントが存在する場合はエラーをスロー
5. assertJsonNodeによるノード検証
   └─ 不正なノードタイプ（テンプレートリテラル式等）をエラー
6. wrapExpressionでJsonRootノードにラップ
   └─ 最終的なASTを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: parseJson] --> B{parseExpression実行}
    B -->|成功| C[コメント取得]
    B -->|失敗| D{allowEmpty?}
    D -->|Yes| E[parseEmptyJson試行]
    D -->|No| F[エラースロー]
    E -->|成功| G[コメントのみ取得]
    E -->|失敗| F
    C --> H{allowComments?}
    H -->|No| I{コメント存在?}
    I -->|Yes| J[コメントエラースロー]
    H -->|Yes| K[assertJsonNode]
    I -->|No| K
    G --> K
    K -->|成功| L[wrapExpression]
    K -->|失敗| F
    L --> M[JsonRoot AST返却]
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-011-01 | JSON許可ノード | ArrayExpression、ObjectExpression、ObjectProperty、リテラルノードのみ許可 | 常時 |
| BR-011-02 | JSON5拡張許可 | Infinity、NaN、undefinedをIdentifierとして許可 | JSON5パーサー使用時 |
| BR-011-03 | 単項演算子許可 | +/- 演算子は数値リテラルおよびInfinity/NaNの前でのみ許可 | 常時 |
| BR-011-04 | コメント制御 | json-stringifyパーサーではコメント禁止 | json-stringifyパーサー使用時 |
| BR-011-05 | 空ファイル許可 | jsoncパーサーのみ空ファイルを許可 | jsoncパーサー使用時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし（純粋なテキスト処理）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | SyntaxError | JSON構文エラー | エラー位置を表示してユーザーに通知 |
| - | CommentError | コメント禁止設定でコメント存在 | "Comment is not allowed in JSON." |
| - | ComputedKeyError | 計算されたキーの使用 | "Computed key is not allowed in JSON." |
| - | ShorthandError | プロパティ短縮記法の使用 | "Shorthand property is not allowed in JSON." |
| - | OperatorError | 不正な演算子使用 | "Operator 'xxx' is not allowed in JSON." |
| - | IdentifierError | 不正な識別子使用 | "Identifier 'xxx' is not allowed in JSON." |

### リトライ仕様

パースエラーはリトライ不可（入力テキストの修正が必要）

## トランザクション仕様

トランザクション管理なし（ステートレスな処理）

## パフォーマンス要件

- 通常のJSONファイル（〜100KB）: 10ms以下
- 大規模JSONファイル（〜1MB）: 100ms以下

## セキュリティ考慮事項

- ユーザー入力のJSONをそのままパースするため、悪意あるコード実行の心配なし（evalは使用しない）
- Babelパーサーによる安全なパース処理

## 備考

- package.json、package-lock.json、composer.jsonはjson-stringifyパーサーを使用（コメント禁止、厳密なJSON形式）
- 一部の自動生成ファイル（MODULE.bazel.lock等）は意図的にフォーマット対象外

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

パース結果のAST構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | json.js | `src/language-json/parse/json.js` | JsonRootノード構造、wrapExpression関数の役割 |

**読解のコツ**: ASTノードタイプは Babel の仕様に準拠している。JsonRootは Prettier 独自のラッパーノード。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/language-json/index.js` | モジュールエクスポート構造 |
| 2-2 | parsers.js | `src/language-json/parsers.js` | 各パーサー（json, json5, jsonc, json-stringify）の定義 |

**主要処理フロー**:
1. **1-3行目**: languages、parsers、printersのエクスポート
2. **4-8行目**: jsonパーサーの定義（hasPragma常時true）
3. **9-11行目**: json5パーサーの定義（デフォルトオプション）
4. **10-12行目**: jsoncパーサーの定義（allowEmpty: true）
5. **13-16行目**: json-stringifyパーサーの定義（allowComments: false）

#### Step 3: パース処理の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | json.js | `src/language-json/parse/json.js` | メインのパースロジック |

**主要処理フロー**:
- **36-73行目**: parseJson関数 - メインのパース処理
- **41-60行目**: Babelパーサーの呼び出しとエラーハンドリング
- **62-64行目**: コメント禁止時の検証
- **66-68行目**: 空ファイル以外でのノード検証
- **70行目**: wrapExpressionによるJsonRootラップ
- **87-172行目**: assertJsonNode関数 - JSON仕様準拠の検証

#### Step 4: プリンター処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | json.js | `src/language-json/print/json.js` | AST to Doc変換処理 |

**主要処理フロー**:
- **6-71行目**: printJson関数 - ノードタイプ別の出力処理
- **9-10行目**: JsonRootの処理
- **11-27行目**: ArrayExpressionの処理
- **28-39行目**: ObjectExpressionの処理

### プログラム呼び出し階層図

```
prettier.format(text, {parser: "json"})
    │
    ├─ loadBuiltinPlugins()
    │      └─ language-json/index.js
    │             ├─ parsers (json, json5, jsonc, json-stringify)
    │             └─ printers (estree-json, estree)
    │
    ├─ core.parse()
    │      └─ parsers.json.parse(text)
    │             └─ parseJson(text, options)
    │                    ├─ parseExpression() [Babel]
    │                    ├─ assertJsonNode()
    │                    └─ wrapExpression()
    │
    └─ core.print()
           └─ printers["estree-json"].print()
                  └─ printJson(path, options, print)
```

### データフロー図

```
[入力]               [処理]                    [出力]

JSON テキスト ───▶ parseJson() ───▶ JsonRoot AST
     │                   │
     │                   ├─ parseExpression (Babel)
     │                   │
     │                   ├─ assertJsonNode (検証)
     │                   │
     │                   └─ wrapExpression (ラップ)
     │
     └────────────▶ printJson() ───▶ Doc (中間表現)
                         │
                         └─ hardline, indent, join
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/language-json/index.js` | ソース | モジュールエントリーポイント |
| parsers.js | `src/language-json/parsers.js` | ソース | パーサー定義 |
| json.js | `src/language-json/parse/json.js` | ソース | JSONパース処理 |
| printers.js | `src/language-json/printers.js` | ソース | プリンター登録 |
| json.js | `src/language-json/print/json.js` | ソース | JSON印刷処理 |
| languages.evaluate.js | `src/language-json/languages.evaluate.js` | ソース | 言語定義 |
| utilities.js | `src/language-json/utilities.js` | ソース | ユーティリティ関数 |
| get-visitor-keys.js | `src/language-json/get-visitor-keys.js` | ソース | ASTトラバース用キー定義 |
| massage-ast/index.js | `src/language-json/massage-ast/index.js` | ソース | ASTマッサージ処理 |
