# 機能設計書 75-JSON処理

## 概要

本ドキュメントは、Godotエンジンにおける JSON処理機能の設計を記述する。JSONデータのパース、生成、Godot Variant型との相互変換機能を提供する。

### 本機能の処理概要

JSON処理機能は、JSON（JavaScript Object Notation）形式のデータをGodotのVariant型に変換し、またその逆変換を行う。設定ファイル、セーブデータ、WebAPIレスポンスなど様々な用途で使用される。

**業務上の目的・背景**：現代のゲーム開発において、JSONは設定データ、ゲームの状態保存、サーバー通信など様々な場面で利用される標準的なデータ形式となっている。JSON処理機能は、こうしたデータ交換を効率的に行うための基盤を提供する。

**機能の利用シーン**：
- ゲーム設定ファイルの読み込み・保存
- セーブデータの永続化
- WebAPIからのレスポンス解析
- MODシステムでの設定データ読み込み
- ゲーム内データテーブルの管理

**主要な処理内容**：
1. JSON文字列のパース（parse）
2. VariantからJSON文字列への変換（stringify）
3. ネイティブ型への変換（to_native, from_native）
4. エラー情報の取得（行番号、メッセージ）
5. 循環参照の検出と処理
6. リソースローダー/セーバー連携

**関連システム・外部連携**：ResourceLoader、ResourceSaver、FileAccess

**権限による制御**：特になし（すべてのスクリプトから利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当画面なし | - | JSONは特定画面に限定されない汎用機能 |

## 機能種別

ユーティリティ / データ交換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| json_text | String | Yes | JSON文字列 | JSON構文チェック |
| data | Variant | Yes | シリアライズ対象データ | - |
| indent | String | No | インデント文字列（デフォルト: ""） | - |
| sort_keys | bool | No | キーのソート（デフォルト: true） | - |
| full_precision | bool | No | 浮動小数点の完全精度（デフォルト: false） | - |
| keep_text | bool | No | パース後にテキストを保持（デフォルト: false） | - |

### 入力データソース

- 文字列引数（スクリプトから）
- .jsonファイル（リソースローダー経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | Variant | パース結果（Dictionary/Array/基本型） |
| error_line | int | エラー発生行 |
| error_message | String | エラーメッセージ |
| parsed_text | String | パース済みJSON文字列 |

### 出力先

- スクリプトへのVariant返却
- .jsonファイル（リソースセーバー経由）

## 処理フロー

### 処理シーケンス

```
1. JSON文字列の入力
2. トークナイザーによる字句解析
   └─ _get_token()でトークンを順次取得
3. パーサーによる構文解析
   └─ _parse_value()で値を再帰的にパース
4. Variant構造の構築
   └─ _parse_object()/_parse_array()でネスト処理
5. 結果返却またはエラー報告
```

### フローチャート

```mermaid
flowchart TD
    A[JSON文字列入力] --> B[トークナイズ]
    B --> C{トークン種別?}
    C -->|{| D[オブジェクトパース]
    C -->|[| E[配列パース]
    C -->|値| F[値パース]
    C -->|EOF| G[完了]
    C -->|エラー| H[エラー返却]
    D --> I[キー:値の繰り返し]
    I --> J[Dictionary構築]
    E --> K[要素の繰り返し]
    K --> L[Array構築]
    F --> M[Variant変換]
    J --> G
    L --> G
    M --> G
    G --> N[結果返却]
    H --> O[エラー情報設定]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-75-01 | 循環参照検出 | 配列/辞書の循環参照を検出してエラー | stringify実行時 |
| BR-75-02 | 深度制限 | MAX_RECURSION_DEPTHを超えるとエラー | パース/生成時 |
| BR-75-03 | NaN処理 | NaN値はnullに変換し警告 | stringify実行時 |
| BR-75-04 | Infinity処理 | Infinityは1e99999/-1e99999に変換 | stringify実行時 |
| BR-75-05 | UTF-16サロゲート | UTF-16サロゲートペアを正しく処理 | 文字列パース時 |

### トークン種別

```
TK_CURLY_BRACKET_OPEN  '{'
TK_CURLY_BRACKET_CLOSE '}'
TK_BRACKET_OPEN        '['
TK_BRACKET_CLOSE       ']'
TK_IDENTIFIER          true/false/null
TK_STRING              "..."
TK_NUMBER              数値
TK_COLON               ':'
TK_COMMA               ','
TK_EOF                 終端
```

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

本機能はデータベース操作を行わない（インメモリ処理）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_PARSE_ERROR | 構文エラー | 不正なJSON構文 | get_error_line/get_error_messageで詳細確認 |
| ERR_OUT_OF_MEMORY | 深度エラー | ネストが深すぎる | 構造をフラット化 |
| - | 循環参照エラー | 自己参照する構造 | 循環参照を解消 |
| - | 文字列エラー | 未終端の文字列 | JSON構文を修正 |

### リトライ仕様

JSON処理にリトライ機構はない。

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

該当なし（インメモリ処理）

## パフォーマンス要件

- 手書きパーサーによる高速処理
- 大きなJSONファイルは分割処理を推奨
- stringify時のマーカーによる循環参照チェック

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

- from_native/to_nativeのfull_objects/allow_objectsフラグによるオブジェクトシリアライズ制御
- スクリプトパス検証（res://プレフィックス必須）
- 信頼できないJSONのパース時は allow_objects=false を推奨

## 備考

- JSON5形式には非対応（標準JSON仕様のみ）
- コメントは非対応
- 末尾カンマは非対応
- リソースとしてロード/セーブ可能（.jsonファイル）

---

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

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

### 推奨読解順序

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

JSONクラスの基本構造とトークン定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | json.h | `core/io/json.h` | JSONクラス定義 |
| 1-2 | json.cpp | `core/io/json.cpp` | トークン定義（38-49行目） |

**読解のコツ**: JSONクラスはResourceを継承し、パース結果をVariantとして保持する。

#### Step 2: パース処理を理解する

JSON文字列のパース処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | json.cpp | `core/io/json.cpp` | _get_token(), parse()の実装 |

**主要処理フロー**:
1. **196-415行目**: _get_token()でトークナイズ
2. **417-459行目**: _parse_value()で値をパース
3. **461-497行目**: _parse_array()で配列をパース
4. **499-560行目**: _parse_object()でオブジェクトをパース
5. **598-607行目**: parse()でエントリーポイント

#### Step 3: stringify処理を理解する

VariantからJSON文字列への変換処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | json.cpp | `core/io/json.cpp` | _stringify(), stringify()の実装 |

**主要処理フロー**:
1. **57-194行目**: _stringify()で再帰的に変換
2. **613-618行目**: stringify()でエントリーポイント

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

```
JSON::parse()
    │
    ├─ _parse_string()
    │      │
    │      ├─ _get_token()
    │      │      └─ [トークン取得]
    │      │
    │      └─ _parse_value()
    │             │
    │             ├─ _parse_object()
    │             │      └─ [キー:値ペア処理]
    │             │
    │             └─ _parse_array()
    │                    └─ [要素処理]
    │
    └─ [結果設定]

JSON::stringify()
    │
    └─ _stringify()
           │
           ├─ [プリミティブ型変換]
           │
           ├─ [Array処理] ─▶ _stringify() [再帰]
           │
           └─ [Dictionary処理] ─▶ _stringify() [再帰]
```

### データフロー図

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

JSON文字列 ─────────▶ _get_token ────────────▶ Token列
     │                    │
Token ──────────────▶ _parse_value ──────────▶ Variant
     │                    │
Dictionary/Array ───────────────────────────▶ data (パース結果)

Variant ────────────▶ _stringify ────────────▶ JSON文字列
     │                    │
indent/sort_keys ───────────────────────────▶ フォーマット済み出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| json.cpp | `core/io/json.cpp` | ソース | JSON実装 |
| json.h | `core/io/json.h` | ヘッダー | JSON定義 |
| resource_loader.cpp | `core/io/resource_loader.cpp` | ソース | リソースロード |
| resource_saver.cpp | `core/io/resource_saver.cpp` | ソース | リソース保存 |
