> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 構造化出力修復

> 構造化出力修復：Key 単位で有効化でき、モデルが返す不正な JSON をゲートウェイが自動修復。Chat Completions / Responses / Claude / Gemini に対応します。

モデルが[構造化出力](/jp/api/Structured-Output)のシナリオで返す JSON は、パースできない場合があります：出力が `max_tokens` によって切り捨てられている、末尾カンマが付いている、内容が Markdown コードブロックに包まれている、といったケースです。アプリケーション側では通常、このためにリトライや手動修復のロジックを書く必要があります。

**構造化出力修復**（Structured Output Repair）は **Key レベル**の機能で、デフォルトでは無効です。有効にすると、構造化 JSON 出力を宣言した**非ストリーミング**リクエストにおいて、モデルが返した JSON にフォーマットエラーがある場合、AIHubMix ゲートウェイが返却前に自動でパース可能な正当な JSON に修復します。クライアント側のコードを変更する必要はありません。

<Note>
  このスイッチはデフォルトで無効です。有効化していない場合、すべての応答はそのまま返却されます。スイッチは Key ごとに個別に設定でき、有効化すると即座に反映されます。
</Note>

<Card title="Key 管理ページで設定する" icon="key" href="https://console.aihubmix.com/token" horizontal>
  Key を作成または編集し、「構造化出力修復」（Structured Output Repair）スイッチを有効にします。
</Card>

<Frame>
  <img src="https://mintcdn.com/aihubmix/qSKYuy2NVPUOModZ/images/api/structured-output-repair/create-key-json-repair.png?fit=max&auto=format&n=qSKYuy2NVPUOModZ&q=85&s=119802fb4114c18581c6e47c1543620a" alt="AIHubMix の Key 編集パネルで構造化出力修復スイッチを有効にする" width="2886" height="1974" data-path="images/api/structured-output-repair/create-key-json-repair.png" />
</Frame>

***

## 1. 有効になる条件

修復は以下の条件が**すべて満たされた**ときにのみ発生します：

1. リクエストに使用する Key で「構造化出力修復」が有効になっている。
2. リクエストが**非ストリーミング**である（`stream: true` を設定していない）。
3. リクエストが構造化 JSON 出力を宣言している（各プロトコルの宣言フィールドは下表を参照）。
4. モデルが返したテキスト内容が JSON としてパースできない。

| プロトコル            | エンドポイント                                         | 構造化出力の宣言フィールド                                                                          |
| ---------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------- |
| Chat Completions | `/v1/chat/completions`                          | `response_format.type` が `json_object` または `json_schema`                               |
| Responses        | `/v1/responses`                                 | `text.format.type` が `json_schema` または `json_object`                                   |
| Claude Messages  | `/v1/messages`                                  | `output_config.format.type` が `json_schema`                                            |
| Gemini           | `/gemini/v1beta/models/{model}:generateContent` | `generationConfig.responseMimeType` が `application/json`、または `responseSchema` が設定されている |

内容そのものが正当な JSON である場合は、一切変更せずそのまま返却します。

***

## 2. 修復できるフォーマットエラー

**出力の切り捨てにより括弧 / 引用符が閉じていない**（例：`finish_reason` が `length`）：

```text 修復前 theme={null}
{"items": [{"name": "Widget", "price": 9.99}, {"name": "Gad
```

```json 修復後 theme={null}
{"items": [{"name": "Widget", "price": 9.99}, {"name": "Gad"}]}
```

**Markdown コードブロックによる包囲**：

````text 修復前 theme={null}
```json
{"status": "ok", "count": 3}
```
````

```json 修復後 theme={null}
{"status": "ok", "count": 3}
```

**末尾カンマ**：

```text 修復前 theme={null}
{"a": 1, "b": 2,}
```

```json 修復後 theme={null}
{"a": 1, "b": 2}
```

**シングルクォート**：

```text 修復前 theme={null}
{'name': 'Widget'}
```

```json 修復後 theme={null}
{"name": "Widget"}
```

**キー名が引用符で囲まれていない**：

```text 修復前 theme={null}
{name: "Widget", price: 9.99}
```

```json 修復後 theme={null}
{"name": "Widget", "price": 9.99}
```

**テキストと JSON の混在**（JSON の前後に説明テキストが付いている）：

```text 修復前 theme={null}
Here is the JSON you requested: {"name": "Widget", "price": 9.99}
```

```json 修復後 theme={null}
{"name": "Widget", "price": 9.99}
```

修復は保守的な戦略を採用しています：

* 修復は JSON の構文の補完または正規化のみを行い、**数値と文字列の内容は原文のまま維持され、精度の損失や書き換えは発生しません**。
* 修復結果は正当な JSON オブジェクトまたは配列でなければならず、かつ原文との差異が妥当な範囲内である必要があります。いずれかの条件が満たされない場合は修復を諦め、元の内容をそのまま返却します。

***

## 3. 応答が修復されたかどうかの判別方法

修復が発生した場合、プログラムから読み取れる / 目視で確認できる 2 つのシグナルがあります：

1. **応答ヘッダー** `X-JSON-Repaired: true`（修復が発生していない場合、この応答ヘッダーはありません）。
2. **呼び出しログの備考**：[呼び出し記録ページ](https://console.aihubmix.com/logs)の該当リクエストの備考列に `This request gateway automatically corrected the JSON format issue in the model output.` が表示されます。

Token 使用量と課金はモデルの元の出力に基づいて計算され、修復によって課金結果が変わることはありません。

***

## 4. 完全な例

商品情報の生成を例に、リクエストは `json_schema` で構造化出力を宣言します。スイッチを有効にすると、モデルの出力に上記のフォーマットエラーがあっても、取得した `content` はそのままパースできます：

<CodeGroup>
  ```python Python theme={null}
  import json
  import os
  import requests

  response = requests.post(
      "https://aihubmix.com/v1/chat/completions",
      headers={
          "Authorization": f"Bearer {os.environ['AIHUBMIX_API_KEY']}",
          "Content-Type": "application/json",
      },
      json={
          "model": "gpt-5.2",
          "messages": [
              {"role": "user", "content": "Generate a product listing for a wireless keyboard."}
          ],
          "response_format": {
              "type": "json_schema",
              "json_schema": {
                  "name": "product",
                  "schema": {
                      "type": "object",
                      "properties": {
                          "name": {"type": "string"},
                          "price": {"type": "number"},
                          "description": {"type": "string"},
                      },
                      "required": ["name", "price"],
                      "additionalProperties": False,
                  },
              },
          },
      },
  )

  repaired = response.headers.get("X-JSON-Repaired") == "true"
  product = json.loads(response.json()["choices"][0]["message"]["content"])
  print(product, "repaired:", repaired)
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://aihubmix.com/v1/chat/completions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.AIHUBMIX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "gpt-5.2",
      messages: [
        { role: "user", content: "Generate a product listing for a wireless keyboard." },
      ],
      response_format: {
        type: "json_schema",
        json_schema: {
          name: "product",
          schema: {
            type: "object",
            properties: {
              name: { type: "string" },
              price: { type: "number" },
              description: { type: "string" },
            },
            required: ["name", "price"],
            additionalProperties: false,
          },
        },
      },
    }),
  });

  const repaired = response.headers.get("X-JSON-Repaired") === "true";
  const data = await response.json();
  const product = JSON.parse(data.choices[0].message.content);
  console.log(product, "repaired:", repaired);
  ```

  ```shell curl theme={null}
  curl -sD - https://aihubmix.com/v1/chat/completions \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-5.2",
      "messages": [
        {"role": "user", "content": "Generate a product listing for a wireless keyboard."}
      ],
      "response_format": {
        "type": "json_schema",
        "json_schema": {
          "name": "product",
          "schema": {
            "type": "object",
            "properties": {
              "name": {"type": "string"},
              "price": {"type": "number"},
              "description": {"type": "string"}
            },
            "required": ["name", "price"],
            "additionalProperties": false
          }
        }
      }
    }'
  ```
</CodeGroup>

修復を実際に観察してみたい場合は、`max_tokens` を小さい値（例：`80`）に設定して出力を切り捨てさせます：応答の `finish_reason` は `length` となり、`content` は修復後の正当な JSON になり、応答ヘッダーに `X-JSON-Repaired: true` が付与されます。

***

## 5. 制限事項と注意点

<Warning>
  ストリーミングリクエスト（`stream: true`）は修復を行わず、そのまま転送します。修復機能が必要な場合は非ストリーミングリクエストを使用してください。
</Warning>

<Warning>
  修復は内容が JSON としてパースできることを保証しますが、切り捨てによって失われたデータは復元できません。`finish_reason` / `stop_reason` も併せて確認し、出力が切り捨てられている場合は必要に応じて `max_tokens` を増やしてリトライすることをおすすめします。
</Warning>

* **構文の修復**：フィールド名やフィールドの型があなたの schema に適合しているかどうかは、依然としてアプリケーション側での検証が必要です。
* **ツール呼び出しパラメータは修復の対象外**：`tool_calls` / `function_call` のパラメータ JSON は修復しません。ツールパラメータは実行前に常にアプリケーション側で検証してください。
* **複数テキストブロックの出力は修復しない**：モデルの出力が複数のテキストブロックを含む場合（例：Gemini が複数の `parts` を返す場合）はそのまま返却します。
* **推論内容は影響を受けない**：`reasoning_content`、Gemini の thought 部分などの推論テキストは修復に関与しません。

***

## よくある質問 FAQ

**修復によって返却内容の数値やテキストが変わりますか？**

いいえ。修復は JSON の構文の補完または正規化（閉じ括弧の補完、末尾カンマの除去、引用符の正規化、コードブロックマークの剥離）のみを行い、数値と文字列の内容はモデル出力の原文のまま維持されます。

**スイッチを有効にすると、構造化出力を宣言していない通常のリクエストに影響しますか？**

いいえ。`response_format` などの構造化出力フィールドを宣言していないリクエスト、およびすべてのストリーミングリクエストの応答は、いずれもそのまま返却されます。

**修復によって追加課金が発生したり、token 使用量が変わったりしますか？**

いいえ。Token 使用量と課金はモデルの元の出力に基づいて計算され、修復の過程で追加費用は発生しません。

**修復後の JSON は必ず私が定義した schema に適合しますか？**

修復は内容が JSON としてパースできることを保証しますが、フィールド名やフィールドの型が schema に適合しているかどうかはモデル出力自体に依存します。アプリケーション側で引き続き schema 検証を残しておくことをおすすめします。
