# 機能設計書: json - JSON解析・生成

## 1. 機能概要

### 1.1 目的
jsonモジュールは、NimプログラミングにおけるJSON（JavaScript Object Notation）データの解析と生成のための高性能な機能を提供する。JSONの読み取り、書き込み、操作、およびNim型との相互変換をサポートする。

### 1.2 機能範囲
- JSON文字列の解析（パース）
- JsonNode型によるJSON表現
- JSON文字列の生成（シリアライズ）
- 値の取得と設定
- 型安全なアクセサ
- `%*`マクロによるリテラル構築
- `to`マクロによるNim型への変換

### 1.3 関連コンポーネント
- `parsejson` モジュール: 低レベルJSONパーサー
- `tables` モジュール: OrderedTable使用
- `streams` モジュール: ストリーム入力対応
- `options` モジュール: Option型対応

## 2. データ構造

### 2.1 型定義

```nim
type
  JsonNodeKind* = enum  ## JSONノードの種類
    JNull,              ## null値
    JBool,              ## 真偽値
    JInt,               ## 整数
    JFloat,             ## 浮動小数点数
    JString,            ## 文字列
    JObject,            ## オブジェクト
    JArray              ## 配列

  JsonNode* = ref JsonNodeObj  ## JSONノード参照型
  JsonNodeObj* {.acyclic.} = object
    isUnquoted: bool  ## 数値文字列の場合true
    case kind*: JsonNodeKind
    of JString:
      str*: string
    of JInt:
      num*: BiggestInt
    of JFloat:
      fnum*: float
    of JBool:
      bval*: bool
    of JNull:
      nil
    of JObject:
      fields*: OrderedTable[string, JsonNode]
    of JArray:
      elems*: seq[JsonNode]
```

### 2.2 特徴
- **オブジェクト変異型**: `JsonNode`は`kind`フィールドによって内部構造が変わる
- **キー順序保持**: `JObject`は`OrderedTable`を使用し、挿入順序を保持
- **参照型**: `JsonNode`は参照型のため、変更は共有される

## 3. 主要機能

### 3.1 JSON解析

#### parseJson
```nim
proc parseJson*(s: string, rawIntegers = false, rawFloats = false): JsonNode
proc parseJson*(s: Stream, filename = "", rawIntegers = false, rawFloats = false): JsonNode
```
- **目的**: JSON文字列またはストリームをJsonNodeに変換
- **パラメータ**:
  - `rawIntegers`: 大きな整数を文字列として保持
  - `rawFloats`: 浮動小数点を文字列として保持
- **ソース位置**: `lib/pure/json.nim:864-950`付近

### 3.2 JsonNode作成

#### コンストラクタ

| プロシージャ | 説明 | ソース位置 |
|-------------|------|-----------|
| `newJString` | JStringを作成 | 216-218 |
| `newJInt` | JIntを作成 | 227-229 |
| `newJFloat` | JFloatを作成 | 231-233 |
| `newJBool` | JBoolを作成 | 235-237 |
| `newJNull` | JNullを作成 | 239-241 |
| `newJObject` | JObjectを作成 | 243-245 |
| `newJArray` | JArrayを作成 | 247-249 |

#### %演算子
```nim
proc `%`*(s: string): JsonNode     ## 文字列からJString
proc `%`*(n: int): JsonNode        ## 整数からJInt
proc `%`*(n: float): JsonNode      ## 浮動小数点からJFloat
proc `%`*(b: bool): JsonNode       ## 真偽値からJBool
proc `%`*[T](elements: openArray[T]): JsonNode  ## 配列からJArray
proc `%`*[T](table: Table[string, T]): JsonNode  ## テーブルからJObject
proc `%`*[T: object](o: T): JsonNode  ## オブジェクトからJObject
```
- **ソース位置**: `lib/pure/json.nim:315-414`

#### %*マクロ
```nim
macro `%*`*(x: untyped): untyped
```
- **目的**: リテラル構文でJsonNodeを構築
- **使用例**:
```nim
let j = %* {"name": "Alice", "age": 30, "scores": [95, 87, 92]}
```
- **ソース位置**: `lib/pure/json.nim:442-445`

### 3.3 値の取得

#### getプロシージャ

| プロシージャ | 戻り値 | デフォルト値 |
|-------------|--------|------------|
| `getStr` | string | "" |
| `getInt` | int | 0 |
| `getBiggestInt` | BiggestInt | 0 |
| `getFloat` | float | 0.0 |
| `getBool` | bool | false |
| `getFields` | OrderedTable | 空テーブル |
| `getElems` | seq[JsonNode] | @[] |

- **nil安全**: `n`がnilの場合でもデフォルト値を返す
- **ソース位置**: `lib/pure/json.nim:251-303`

### 3.4 アクセス演算子

#### []演算子
```nim
proc `[]`*(node: JsonNode, name: string): JsonNode  ## オブジェクトフィールドアクセス
proc `[]`*(node: JsonNode, index: int): JsonNode     ## 配列インデックスアクセス
proc `[]`*(node: JsonNode, index: BackwardsIndex): JsonNode  ## 逆インデックス
proc `[]`*[U, V](a: JsonNode, x: HSlice[U, V]): JsonNode  ## スライス
```
- **注意**: キーが存在しない場合は`KeyError`を発生
- **ソース位置**: `lib/pure/json.nim:518-564`

#### {}演算子（nil安全）
```nim
proc `{}`*(node: JsonNode, keys: varargs[string]): JsonNode
proc `{}`*(node: JsonNode, index: varargs[int]): JsonNode
```
- **目的**: キーが存在しない場合にnilを返す（例外なし）
- **ソース位置**: `lib/pure/json.nim:581-620`

### 3.5 JSON生成

#### 文字列変換
```nim
proc `$`*(node: JsonNode): string      ## コンパクト形式
proc pretty*(node: JsonNode, indent = 2): string  ## 整形形式
proc toUgly*(result: var string, node: JsonNode)  ## 高速変換
```
- **ソース位置**: `lib/pure/json.nim:708-830`

#### エスケープ処理
```nim
proc escapeJson*(s: string): string            ## 引用符付きエスケープ
proc escapeJsonUnquoted*(s: string): string    ## 引用符なしエスケープ
```
- **ソース位置**: `lib/pure/json.nim:674-706`

### 3.6 イテレータ

```nim
iterator items*(node: JsonNode): JsonNode       ## JArray要素
iterator pairs*(node: JsonNode): tuple[key: string, val: JsonNode]  ## JObjectペア
iterator keys*(node: JsonNode): string          ## JObjectキー
```
- **ソース位置**: `lib/pure/json.nim:832-862`

### 3.7 その他の操作

| プロシージャ | 説明 | ソース位置 |
|-------------|------|-----------|
| `len` | 要素数/フィールド数を取得 | 509-516 |
| `hasKey` | キーの存在確認 | 566-569 |
| `contains` | キー/値の存在確認 | 571-579 |
| `add` | 要素/フィールドの追加 | 305-313 |
| `delete` | フィールドの削除 | 632-637 |
| `copy` | ディープコピー | 639-660 |

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

### 4.1 推奨読解順序

1. **型定義** (184-212行目)
   - `JsonNodeKind`と`JsonNode`の構造を理解

2. **コンストラクタ** (216-249行目)
   - `newJString`等の基本的なノード作成

3. **%演算子** (315-414行目)
   - 各Nim型からJsonNodeへの変換

4. **値取得** (251-303行目)
   - `getStr`, `getInt`等のアクセサ

5. **解析と生成** (864-950行目, 708-830行目)
   - `parseJson`と`$`/`pretty`

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

```
parseJson(s: string) [864行目付近]
├── JsonParser.open()
├── parseJson(p: JsonParser) [再帰]
│   ├── tkString -> newJString()
│   ├── tkInt -> newJInt() / newJRawNumber()
│   ├── tkFloat -> newJFloat() / newJRawNumber()
│   ├── tkTrue/tkFalse -> newJBool()
│   ├── tkNull -> newJNull()
│   ├── tkCurlyLe -> newJObject() + 再帰
│   └── tkBracketLe -> newJArray() + 再帰
└── JsonParser.close()

$node / pretty(node)
└── toUgly(result, node) / toPretty(result, node)
    ├── JArray -> "[" + 再帰 + "]"
    ├── JObject -> "{" + escapeJson(key) + 再帰 + "}"
    ├── JString -> escapeJson(str)
    ├── JInt -> addInt()
    ├── JFloat -> addFloat()
    ├── JBool -> "true"/"false"
    └── JNull -> "null"
```

### 4.3 データフロー図

```
[JSON文字列]
      │
      ▼
┌─────────────────────────────────┐
│     parseJson()                  │
│  ┌────────────────────────────┐  │
│  │ JsonParser (lexer/parser) │  │
│  └───────────┬────────────────┘  │
└──────────────┼───────────────────┘
               │
               ▼
         JsonNode ◄──── %* マクロ
               │            │
               │        [Nimリテラル]
               │
    ┌──────────┼──────────┐
    │          │          │
    ▼          ▼          ▼
  []演算子   {}演算子   getXxx
  (厳密)    (nil安全)  (デフォルト値)
    │          │          │
    └──────────┼──────────┘
               │
               ▼
         [Nim値]
               │
               ▼
    $ / pretty / toUgly
               │
               ▼
       [JSON文字列]
```

### 4.4 読解のコツ

- **オブジェクト変異型**: `case kind`によるバリアントオブジェクトのパターンを理解
- **isUnquoted**: 大きな数値を文字列として保持する際の引用符制御
- **nil安全性**: `{}`演算子とget系プロシージャはnilを適切に処理

## 5. 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `lib/pure/json.nim` | ソース | メイン実装 |
| `lib/pure/parsejson.nim` | ソース | 低レベルパーサー |
| `lib/pure/tables.nim` | ソース | OrderedTable |
| `lib/pure/streams.nim` | ソース | ストリーム入力 |

## 6. 設計上の考慮事項

### 6.1 パフォーマンス
- `toUgly`は`pretty`より高速（フォーマットなし）
- `OrderedTable`でキー順序を保持しつつ効率的なアクセス
- `{.acyclic.}`で循環参照チェックを省略

### 6.2 互換性
- RFC 7159準拠のJSON仕様
- NaN/Inf/−Infは文字列として表現
- 大きな整数は`newJRawNumber`で精度を保持

### 6.3 エラー処理
- `parseJson`は不正なJSONで`JsonParsingError`を発生
- `[]`演算子は存在しないキーで`KeyError`を発生
- `{}`演算子はエラーの代わりにnilを返す
