AI活用

AIにJSONを出力させる方法|プロンプト指定とスキーマ指定の違い

AIの出力をWebアプリで扱えるJSONにする方法を解説。プロンプト指定、JSON mode、JSON.parse、バリデーション、Structured Outputsとの違い、よくあるエラーをJavaScript実装向けに整理します。

この記事の目次
  1. 結論:AIのJSON出力は小さく指定し、必ずアプリ側で検証する
  2. AIにJSONを出力させる方法で作るもの
  3. 前提環境を確認する
  4. 方法1:プロンプトでJSON形式を指定する
  5. 方法2:JSON modeで有効なJSONに近づける
  6. 最小コードを書く
  7. 処理の流れを分解する
  8. 実務向けに拡張する
  9. Structured OutputsやFunction Callingとの違い
  10. よくあるエラーと原因
  11. JSON.parseでエラーになる
  12. キー名が変わる
  13. 型が変わる
  14. 配列とオブジェクトが入れ替わる
  15. 出力が途中で切れる
  16. 想定外のカテゴリが返る
  17. セキュリティ・料金・運用の注意点
  18. 次に読むべき関連記事
  19. まとめ
  20. 参考リンク

AI APIをWebアプリに組み込むと、自然な文章だけでなく、アプリ側で処理できるJSONが欲しくなる場面が増えます。問い合わせをカテゴリ分類する、記事タイトル案を配列で返す、入力文から項目を抽出する、レビュー結果をスコア付きで返す、といった処理では、文章よりJSONのほうが扱いやすいからです。

ただし、AIに「JSONで返して」と書くだけでは、毎回安全にパースできるとは限りません。説明文が混ざる、キー名が変わる、配列になるはずが文字列になる、途中で出力が切れる、といった問題が起きます。

この記事では、AIにJSONを出力させる基本、プロンプト指定とJSON modeの違い、Structured Outputsとの役割分担、JavaScriptでのパースと検証、よくあるエラーを、Web開発者向けに整理します。

前提として、AIへの指示設計を整理したい場合は、プロンプトエンジニアリングとは?AIに安定した出力をさせる基本 を読むと流れをつかみやすいです。固定指示の考え方は、システムプロンプトとは?AIアプリの振る舞いを固定する設計方法 に分けています。

この記事の内容は、2026年7月9日時点のOpenAI API公式ドキュメントをもとにしています。APIの書き方、JSON mode、Structured Outputs、Function Callingの仕様は変わるため、実装前には必ず公式ドキュメントを確認してください。

結論:AIのJSON出力は小さく指定し、必ずアプリ側で検証する

AIにJSONを出力させるときの基本は、次の3つです。

  • 出したいJSONの形を小さく決める
  • JSONだけを返すように明示する
  • 受け取ったJSONをアプリ側でパース・検証する

OpenAIのStructured Outputsドキュメントでは、JSON modeは有効なJSONを出しやすくする基本機能であり、Structured Outputsは指定したJSON Schemaへの一致まで扱う機能として説明されています。JSON modeは便利ですが、特定のスキーマに必ず一致することまでは保証しません。

つまり、AI JSON出力は次のように段階で考えます。

方法 できること 向いている場面
プロンプトでJSONを指定 出力形式を文章で頼む 試作、軽い下書き、手動確認前提
JSON mode 有効なJSONを出しやすくする 簡単な構造化、パース前提の実装
Structured Outputs JSON Schemaに沿った出力を狙う 本番の厳密なデータ構造、UI生成、DB保存
Function Calling AIにアプリ側の関数やツールを選ばせる 外部API実行、DB検索、処理の分岐

この記事では、まずJSON出力の基本と最小実装を扱います。JSON Schemaで厳密に固定する方法は、後続の `structured-outputs-basics` で深掘りします。

AIにJSONを出力させる方法で作るもの

この記事では、問い合わせ文をAIに渡し、次のようなJSONを返してもらう例で考えます。

{
  "category": "billing",
  "priority": "high",
  "summary": "請求金額が想定より高い理由の確認依頼",
  "needs_human_review": true
}

このようなJSONが得られると、Webアプリ側で次のように使えます。

  • カテゴリごとに担当チームへ振り分ける
  • 優先度が高い問い合わせを管理画面で上に出す
  • 要約を一覧画面に表示する
  • 人間確認が必要なものだけ別キューへ送る
  • 後から分析しやすい形でDBに保存する

自然文のままでは、アプリ側が「どこがカテゴリで、どこが要約か」を判断しにくくなります。JSONにすると、JavaScriptやPHP、Reactなどで値を取り出して扱いやすくなります。

APIレスポンスとしてJSONを扱う基本は、JavaScriptでJSONデータを取得する方法 も参考になります。Reactで取得したJSONを表示する流れは、Reactで取得したJSONデータを画面に表示する方法 ともつながります。

前提環境を確認する

この記事のコード例は、考え方を示すための最小例です。実際のSDK、モデル名、レスポンス形式は、利用しているAPIの公式ドキュメントに合わせてください。

前提は次のとおりです。

  • サーバー側のJavaScriptからAI APIを呼び出す
  • APIキーは環境変数などで管理する
  • ユーザー入力はそのまま信用しない
  • AIの出力は必ずパースと検証を行う
  • 厳密なスキーマ固定はStructured Outputsへ分ける

AI APIをブラウザから直接呼ぶと、APIキー漏洩や利用量制御の問題が起きます。AI機能はサーバー側を経由するのが基本です。クライアントとサーバーの役割は、クライアントサーバーシステムとは も参考になります。

方法1:プロンプトでJSON形式を指定する

最も簡単なのは、プロンプトに「JSONだけで返してください」と書く方法です。

次の問い合わせ文を分類してください。

出力はJSONだけにしてください。説明文やMarkdownは不要です。

形式:
{
  "category": "billing | login | bug | cancellation | other",
  "priority": "low | medium | high",
  "summary": "50文字以内の要約",
  "needs_human_review": true
}

問い合わせ文:
先月より請求金額が高い理由を確認したいです。

この方法は、すぐ試せるのが利点です。プロンプトエンジニアリングの記事で扱ったように、目的、入力、制約、出力形式を整理して書くと、ある程度安定します。

ただし、プロンプト指定だけでは次のような問題が起きます。

  • JSONの前後に説明文が混ざる
  • ダブルクォートではなくシングルクォートになる
  • キー名が `needsReview` などに変わる
  • booleanのはずが `”true”` の文字列になる
  • 出力が途中で切れてJSONとして壊れる

手動で見るだけなら問題にならない場合もありますが、Webアプリで `JSON.parse()` するなら、壊れる前提で設計します。

方法2:JSON modeで有効なJSONに近づける

OpenAI APIでは、JSON modeを使うことで、モデルの出力を有効なJSONにしやすくできます。Responses APIでは `text.format` に `{ “type”: “json_object” }` を指定する形が説明されています。

概念コードは次のようになります。

const response = await client.responses.create({
  model: process.env.AI_MODEL,
  instructions: `
問い合わせ分類AIです。
必ずJSONだけを返してください。
説明文、Markdown、コードフェンスは出力しないでください。
`,
  input: `
問い合わせ文を分類してください。

返すJSON:
- category: billing, login, bug, cancellation, other のどれか
- priority: low, medium, high のどれか
- summary: 50文字以内
- needs_human_review: boolean

問い合わせ文:
${inquiryText}
`,
  text: {
    format: {
      type: "json_object"
    }
  }
});

const rawText = response.output_text;
const data = JSON.parse(rawText);

OpenAIのStructured Outputsドキュメントでは、JSON modeを使う場合でも、会話内のどこかでJSONを生成するよう明示的に指示する必要があると説明されています。JSON modeの設定だけでなく、システムプロンプトや入力側でも「JSONだけ」と明示します。

また、JSON modeは有効なJSONを出しやすくしますが、特定のスキーマに必ず一致するわけではありません。スキーマ一致が必要なら、Structured Outputsを検討します。

最小コードを書く

ここでは、AIの出力を受け取り、`JSON.parse()` して、最低限の検証を行う流れを作ります。

function validateInquiryJson(value) {
  const categories = ["billing", "login", "bug", "cancellation", "other"];
  const priorities = ["low", "medium", "high"];

  if (!value || typeof value !== "object") {
    return false;
  }

  if (!categories.includes(value.category)) {
    return false;
  }

  if (!priorities.includes(value.priority)) {
    return false;
  }

  if (typeof value.summary !== "string" || value.summary.length === 0) {
    return false;
  }

  if (typeof value.needs_human_review !== "boolean") {
    return false;
  }

  return true;
}

async function classifyInquiry(client, inquiryText) {
  const response = await client.responses.create({
    model: process.env.AI_MODEL,
    instructions: `
問い合わせ分類AIです。
必ずJSONだけを返してください。
説明文やMarkdownは出力しないでください。
`,
    input: `
問い合わせ文を分類してください。

JSONの形式:
{
  "category": "billing | login | bug | cancellation | other",
  "priority": "low | medium | high",
  "summary": "50文字以内の要約",
  "needs_human_review": true
}

問い合わせ文:
${inquiryText}
`,
    text: {
      format: {
        type: "json_object"
      }
    }
  });

  let data;

  try {
    data = JSON.parse(response.output_text);
  } catch {
    throw new Error("AI output is not valid JSON");
  }

  if (!validateInquiryJson(data)) {
    throw new Error("AI output does not match expected fields");
  }

  return data;
}

このコードは、最小限の考え方です。本番では、入力の長さ制限、ログ、リトライ、ユーザー権限、個人情報の扱い、エラー時の表示を追加します。

処理の流れを分解する

AI JSON出力は、次の流れで考えると実装しやすくなります。

ユーザー入力
  ↓
入力検証
  ↓
プロンプトとJSON形式を指定
  ↓
AI APIへ送信
  ↓
JSON文字列を受け取る
  ↓
JSON.parse
  ↓
必須項目・型・値を検証
  ↓
UI表示・DB保存・人間確認へ分岐

重要なのは、AIが返したJSONをそのまま信用しないことです。

たとえば、次のような出力は、見た目は近くてもアプリ側では扱いづらくなります。

{
  "category": "請求",
  "priority": "高",
  "summary": "",
  "needs_human_review": "yes"
}

人間には意味が分かりますが、アプリ側では `category` が想定値ではなく、`priority` も英語の列挙値ではなく、`needs_human_review` もbooleanではありません。AIの出力は、必ずアプリ側の期待値へ合っているか確認します。

実務向けに拡張する

最小実装が動いたら、次のように拡張します。

拡張 目的
入力制限 トークン増加や想定外入力を防ぐ 問い合わせ文は5000文字まで
列挙値の固定 アプリ側の分岐を安定させる categoryは5種類だけ
型チェック DB保存やUI表示の事故を防ぐ boolean、number、stringを確認する
リトライ 一時的な形式崩れに対応する JSON不正なら1回だけ再生成する
人間確認 判断が難しいものを安全に扱う 不明カテゴリはレビューキューへ送る
ログ 失敗原因を追えるようにする モデル名、プロンプトバージョン、usageを保存する

AI出力をそのまま画面に出すだけなら、多少の揺れは許容できる場合があります。しかし、DBに保存する、ワークフローを分岐する、外部APIを呼ぶ、ユーザーへ自動返信する場合は、検証を強める必要があります。

Structured OutputsやFunction Callingとの違い

AI JSON出力を考えるときは、Structured OutputsとFunction Callingとの違いも押さえておくと混乱しにくくなります。

方法 主な目的 この記事での扱い
JSON mode 有効なJSONとして返しやすくする この記事の中心
Structured Outputs JSON Schemaに沿った出力を得る 次の記事で深掘り
Function Calling AIにアプリ側の関数やツールを選ばせる 外部処理連携の記事で深掘り

OpenAIのStructured Outputsドキュメントでは、モデルをツールや関数、データに接続する場合はFunction Calling、ユーザーへの応答を構造化したい場合はStructured Outputsを使う考え方が示されています。

また、JSON modeは有効なJSONを出す助けになりますが、スキーマ一致までは保証しません。OpenAIの最新モデル向けガイドでも、期待する出力スキーマをプロンプト内で説明しすぎるより、Structured Outputsを使う考え方が示されています。

この記事では、まずAIの出力をJSONとして受け取り、アプリ側で安全に扱う基本を押さえます。

よくあるエラーと原因

AI JSON出力では、次のようなエラーが起きやすいです。

JSON.parseでエラーになる

JSONの前後に説明文、Markdownのコードフェンス、余計なコメントが混ざっている可能性があります。プロンプトで「JSONだけ」と明示し、JSON modeを使い、パース失敗時の処理を用意します。

キー名が変わる

`needs_human_review` を期待しているのに、`needsReview` や `human_review` になることがあります。キー名を明示し、検証で弾きます。厳密に固定したい場合はStructured Outputsを検討します。

型が変わる

booleanのはずが文字列、numberのはずが説明文になることがあります。`typeof` やバリデーションライブラリで確認します。

配列とオブジェクトが入れ替わる

1件の問い合わせではオブジェクト、複数件では配列にしたい場合は、入力件数と出力形式を明確に分けます。処理側でも配列かどうかを確認します。

出力が途中で切れる

出力が長すぎる、コンテキスト上限に近い、最大出力が足りないと、JSONが途中で切れることがあります。項目数を減らし、出力を短くし、コンテキストウィンドウとトークンを確認します。

想定外のカテゴリが返る

ラベル定義が曖昧な場合に起きます。カテゴリの説明、例、迷ったときのルールを追加します。それでも本番では検証で弾きます。

セキュリティ・料金・運用の注意点

AI JSON出力は便利ですが、Webアプリに組み込むときは安全面と運用面も考えます。

  • ユーザー入力をそのまま信じない
  • AIが返したJSONをそのままDB更新や外部API実行に使わない
  • 個人情報や機密情報を必要以上に渡さない
  • パース失敗や検証失敗をログに残す
  • 失敗時にユーザーへ見せるメッセージを用意する
  • 長すぎる入力や出力でトークンが増えすぎないようにする
  • モデル変更時にJSON出力が崩れないか再テストする

トークン量や料金は、入力プロンプト、出力JSON、例文、会話履歴で増えます。基本は AIのトークンとは? を参考にしてください。長文入力や履歴の扱いは、コンテキストウィンドウとは? で整理しています。

安全面では、システムプロンプトに「危険なことをしない」と書くだけでは不十分です。権限、検証、ログ、人間確認が必要です。基本的な注意点は、生成AIの安全な使い方 も参考になります。

次に読むべき関連記事

AIのJSON出力を理解したら、次は厳密な構造固定や外部処理連携へ進むと実装がつながります。

次に進むなら、`structured-outputs-basics` でJSON Schemaによる出力固定を扱うのが自然です。その後に、Function Callingで外部関数やAPIをAIに選ばせる流れへ進むと、AIアプリの実装範囲が広がります。

まとめ

AIにJSONを出力させると、分類、要約、抽出、スコアリング、管理画面表示、DB保存など、Webアプリで扱いやすい形にできます。

ただし、「JSONで返して」と頼むだけでは、本番で安全に使えるとは限りません。プロンプトで出力形式を明示し、JSON modeを使い、`JSON.parse()` とアプリ側のバリデーションで必須項目、型、列挙値を確認します。

JSON modeは有効なJSONを出しやすくする基本機能です。厳密なJSON Schema一致が必要な場合は、Structured Outputsを使う設計へ進みます。まずは小さなJSONから動かし、失敗例をログに残しながら、プロンプトと検証処理を育てていくのがおすすめです。

参考リンク