# 帳票設計書 3-JSONファイル出力

## 概要

本ドキュメントは、Decap CMSにおけるコンテンツデータのJSON形式ファイル出力機能の設計を記述する。jsonFormatterモジュールのtoFileメソッドにより、JavaScriptオブジェクトをJSON文字列にシリアライズしてファイルとして出力する仕組みを定義する。

### 本帳票の処理概要

本帳票は、CMSのコンテンツエディタで編集されたエントリデータをJSON形式のテキストファイルとして出力する機能を定義する。

**業務上の目的・背景**：JSONは最も広く使われるデータ交換フォーマットであり、多くの静的サイトジェネレータやフロントエンドフレームワークでデータソースとして利用される。コンテンツデータをJSON形式で管理することで、APIレスポンスとの互換性やJavaScriptエコシステムとの親和性が高まる。本機能はJSON形式でのコンテンツ管理が求められるプロジェクトにおいて必要である。

**帳票の利用シーン**：コレクション設定でformat: jsonが指定されている場合、またはファイル拡張子が.jsonの場合に、エントリの保存時に本フォーマッタが使用される。Next.js、Nuxt.js等のフレームワークでJSONデータソースを直接参照する場合に利用される。

**主要な出力内容**：
1. エントリのメタデータフィールドをJSONオブジェクトとして出力
2. インデント2スペースでの整形出力（JSON.stringifyの第3引数）
3. JSON標準の型表現（文字列、数値、ブール値、配列、オブジェクト、null）

**帳票の出力タイミング**：エディタ画面で「Save」ボタンを押下した際、resolveFormatで決定されたフォーマッタのtoFileメソッドが呼び出され、JSON文字列が生成される。

**帳票の利用者**：コンテンツ編集者（CMS利用者）、静的サイトジェネレータのビルドシステム

## 帳票種別

データファイル出力（JSON形式テキストファイル）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | エディタ画面 | /collections/{collection}/entries/{slug} | Saveボタン押下 |
| - | 新規エントリ作成画面 | /collections/{collection}/new | Saveボタン押下 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON (.json) |
| 用紙サイズ | N/A（テキストファイル） |
| 向き | N/A |
| ファイル名 | コレクション設定のslugテンプレートに基づく |
| 出力方法 | Gitリポジトリへのコミット（バックエンドAPI経由） |
| 文字コード | UTF-8 |

### PDF固有設定

N/A（テキストファイル出力のため該当なし）

### Excel固有設定

N/A（テキストファイル出力のため該当なし）

## 帳票レイアウト

### レイアウト概要

JSON形式のテキストファイルとして出力される。JSON.stringifyによりインデント2スペースで整形される。

```
┌─────────────────────────────────────┐
│ {                                   │
│   "key1": "value1",                 │
│   "key2": 42,                       │
│   "nested": {                       │
│     "subkey1": "subvalue1"          │
│   },                                │
│   "list": [                         │
│     "item1",                        │
│     "item2"                         │
│   ]                                 │
│ }                                   │
└─────────────────────────────────────┘
```

### ヘッダー部

N/A（JSONファイルにはヘッダー部の概念はない）

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | キー名 | コレクション設定のfieldsで定義されたフィールド名 | collection.fields[].name | JSON key（ダブルクォート囲み） | N/A |
| 2 | 値 | 各フィールドに入力されたデータ | entry.data[fieldName] | JSONの型に応じた表現 | N/A |

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| エントリデータ | エディタで入力された全フィールドデータ | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | オブジェクトのプロパティ定義順 | JSON.stringifyのデフォルト順序 |

### 改ページ条件

N/A（テキストファイルのため該当なし）

## データベース参照仕様

### 参照テーブル一覧

N/A（Gitリポジトリベース）

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| JSONシリアライズ | `JSON.stringify(data, null, 2)` | N/A | JavaScript標準APIによるシリアライズ。replacer引数はnull（全プロパティ対象）、space引数は2（インデント） |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Save操作] --> B[resolveFormat でフォーマッタ決定]
    B --> C[jsonFormatter.toFile 呼び出し]
    C --> D[JSON.stringify でJSON文字列生成]
    D --> E[バックエンドAPIでGitコミット]
    E --> F[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| シリアライズエラー | 循環参照を含むオブジェクトが渡された場合 | TypeError: Converting circular structure to JSON | 入力データの循環参照を除去 |
| BigIntエラー | BigInt値がデータに含まれる場合 | TypeError: Do not know how to serialize a BigInt | BigInt値を数値または文字列に変換 |
| バックエンドエラー | Gitコミットに失敗した場合 | バックエンド固有のエラーメッセージ | ネットワーク接続・認証情報を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1エントリあたり数十〜数百フィールド |
| 目標出力時間 | 数ミリ秒（JSON.stringify処理） |
| 同時出力数上限 | 1件（エディタ操作は逐次処理） |

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

- JSON出力データはGitリポジトリに保存されるため、リポジトリのアクセス制御に依存する
- JSON.stringifyはundefined、Function、Symbolの値を自動的に省略するため、意図せずデータが欠落する可能性がある

## 備考

- JavaScript標準のJSON.stringify APIのみを使用し、外部ライブラリに依存しない最もシンプルな実装
- YAMLやTOMLと異なり、sortedKeysやcommentsのパラメータは非対応
- fromFileはJSON.parseを直接呼び出し、追加の変換処理は行わない
- Frontmatter形式でのJSON使用時はfrontmatter.tsのparsers.jsonが別の処理（先頭/末尾の{}除去）を行う

---

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

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

### 推奨読解順序

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

JSON出力は最もシンプルな構造であり、データ型の理解は容易である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | json.ts | `packages/decap-cms-core/src/formats/json.ts` | toFileメソッドの引数（data: object）のみであり、追加オプションが存在しない点を確認 |

**読解のコツ**: json.tsは全体で9行のファイルであり、JavaScript標準APIのみを使用している。他のフォーマッタ（yaml.ts, toml.ts）との比較で差分を理解するのが効率的。

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

フォーマット解決からJSONフォーマッタが選択される流れを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | formats.ts | `packages/decap-cms-core/src/formats/formats.ts` | resolveFormat関数でformat: json指定時、または拡張子.json時にjsonFormatterが返される流れを確認 |

**主要処理フロー**:
1. **66行目**: `resolveFormat`関数でコレクションのformat指定を確認
2. **47行目**: `formatByName`内で`json`キーに対してjsonFormatterを返却
3. **36行目**: `extensionFormatters`で拡張子jsonに対してjsonFormatterをマッピング

#### Step 3: JSON出力処理を理解する

toFileメソッドの処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | json.ts | `packages/decap-cms-core/src/formats/json.ts` | toFileメソッド（6-8行目）がJSON.stringify(data, null, 2)を呼び出すのみである点を確認 |

**主要処理フロー**:
- **6行目**: `toFile(data: object)` が呼び出される
- **7行目**: `JSON.stringify(data, null, 2)` でインデント2のJSON文字列を生成して返却

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

```
resolveFormat (formats.ts:66)
    |
    +-- formatByName (formats.ts:42)
            |
            +-- jsonFormatter.toFile (json.ts:6)
                    |
                    +-- JSON.stringify (JavaScript built-in)
```

### データフロー図

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

entry.data (Object) -----> JSON.stringify -----> JSON文字列 (.json)
                           (null, 2)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| json.ts | `packages/decap-cms-core/src/formats/json.ts` | ソース | JSONフォーマッタ本体（fromFile/toFile） |
| formats.ts | `packages/decap-cms-core/src/formats/formats.ts` | ソース | フォーマット解決・フォーマッタ選択ロジック |
| frontmatter.ts | `packages/decap-cms-core/src/formats/frontmatter.ts` | ソース | Frontmatter内でのJSON使用時の追加処理（parsers.json） |
