
AIの構造化出力(JSON)を安定させる|崩れたときの復旧まで
「AIの返事をそのままシステムで使いたいから、JSONで返して」——そう頼むと、テストではちゃんと整ったJSONが返ってきます。パースも通る。項目もそろっている。よし、これで組み込める——。
その手応え、よく分かります。自由な文章より、決まった形(構造化された出力)で返ってくれば、あとはプログラムが受け取って処理するだけ。話が早い。でも、AIを業務システムに組み込んだ人が口をそろえて言うのが、「9割9分はきれいなのに、たまに崩れる」という悩みなんですよね。前置きの一文が付く。 `json の囲みが混じる。長い出力が途中で切れる。全角の記号が紛れる。そのたった1%で、処理が止まったり、次のバッチが丸ごとこけたりする。
この記事は、AIの構造化出力(JSON)を本番で安定させる型の話です。完璧に崩れさせない魔法はありません。でも、①型を先に決めて指示する → ②受け取ったら必ず検証する → ③崩れたら静かに立て直す、この3段構えを用意しておけば、「たまの崩れ」で夜中に呼び出される事故はぐっと減らせます。責める話ではないので、気楽に読んでください。
結論:AIのJSON出力は、3つの層で守ります。①出す前——モデル提供元の「構造化出力/JSONモード」機能が使えるなら必ず使い、使えないなら「JSONだけ返す・前置きや説明は書かない・この形で」と例(スキーマ)付きで指示する。②受け取った直後——必ずパースをtry/catchで包み、必須項目の有無・型・値の範囲を機械でチェックする(信じてそのまま使わない)。③崩れたとき——いきなり落とさず、囲み記号の除去などで一度救済を試み、ダメなら「JSONだけで返して」ともう一度だけ頼み、それでもダメなら安全な既定値かエラー通知に倒す。要は「崩れる前提で受け皿を作る」。出力が崩れても、システムは静かに立て直せる形にしておくのが、いちばん効く保険です。
一度に全部を作り込まなくて大丈夫です。 まずは「受け取ったJSONを、そのまま使わずに一度パースと検証を通す」。ここから始めましょう。
何が起きているのか——AIのJSONは「たまに」崩れる

まず、なぜ崩れるのかを共有させてください。AIが不真面目だから、ではありません。仕組みの話です。AI(大規模言語モデル)は、次に来そうな文字を確率的に選んで並べているので、指示に沿った出力を「たいてい」返しますが、「必ず」ではない。だから、同じプロンプトでも日によって、入力によって、ほんの少し違う出し方をします。業務システムに組み込むと、この「ほんの少し」が効いてきます。
現場でよく起きるのは、こんな崩れです。
- 前置き・あとがきが付く:「はい、承知しました。以下がJSONです」「ご確認ください」といった一文が、JSONの前後に混じる。人間相手なら親切ですが、機械がパースすると先頭でつまずきます。
- コードブロックの囲みが混じる:
`jsonと`でくくって返してくる。見た目はきれいでも、その記号ごとパースしようとすると失敗します。 - 途中で切れる:出力の長さ上限(最大トークン数)に当たって、閉じ括弧まで到達せずに切れる。件数の多い一覧を返させたときに起きやすい。
- 細かな体裁のゆれ:末尾に余計なカンマが付く、キーがクオートされていない、全角の記号やスペースが紛れる、
trueのつもりが「はい」になっている——など。 - 項目の欠け・増え:頼んだキーが無い、頼んでいないキーが増える、値が
nullになる。パースは通るのに、業務処理側で「あるはずの項目が無い」と落ちる。
やっかいなのは、どれもテスト環境の少ない試行では出会いにくいこと。手元で5回試して全部きれいだったから、で本番に出すと、1000回のうち数回で顔を出します。だから「動いたからOK」で通ってしまう。ここで一拍おいて、指示・検証・復旧の3層を用意する。次から順に見ていきます。
① 出す前——型を先に決めて、機能で縛る
いちばん効くのは、崩れにくく出させることです。受け取ってから頑張るより、そもそも整った形で返させるほうが安上がりです。
- 提供元の「構造化出力/JSONモード」機能を使えるなら必ず使う:いまは多くのモデル提供元が、出力を決まった形(スキーマ)に沿わせる仕組みを用意しています。返す形をこちらで定義して渡す方式(構造化出力)や、必ずJSONで返させるモード、あるいは「関数の引数」として値を受け取る仕組み(ツール/関数呼び出し)など、呼び方は提供元で違います。これらを使うと、前置きや囲み記号が混じる余地がかなり減ります。まずは自分たちが使っているモデルに、この機能があるか公式ドキュメントを確認するのが第一歩です。
- 機能が使えないときは、指示で縛る:素のプロンプトしか使えない場合は、指示を具体的にします。効くのは、(1)「JSONだけを返す。前置き・説明・コードブロックの囲みは付けない」と明記する、(2)期待する形の例を1つ渡す(キー名・型・入れ子の形を、実物のサンプルで見せる)、(3)「分からない項目は空文字や
nullにする。勝手にキーを増やさない」と決めておく、の3つです。文章で「こう書いて」と説明するより、完成形のサンプルを見せるほうが、AIは形をまねしてくれます。 - 返させる量を欲張らない:一度に何百件も返させると、長さ上限で途中が切れます。件数が多いときは、分けて返させる/1回の件数に上限を設けるほうが安定します。上限や料金の見積もりはAI APIの料金とレート制限を見積もるも下敷きになります。
ここで大事なのは、「整った例を見せる」+「機能で縛る」の合わせ技です。片方だけより、両方やるほうがずっと崩れにくくなります。
② 受け取った直後——信じずに検証する
どれだけ丁寧に頼んでも、崩れは「たまに」起きます。だから受け取った側で、そのまま使わずに一度確かめる。ここを飛ばすと、崩れがそのまま業務データに流れ込みます。
- パースは必ず
try/catchで包む:受け取った文字列をJSONとして読み込む処理は、失敗する前提で例外を捕まえます。ここで落ちても、システム全体は止めずに「この1件は復旧に回す」と切り替えられるようにしておきます。 - 必須項目・型・範囲をチェックする:パースが通っても油断しない。「あるべきキーがそろっているか」「数値であるべき所が数値か」「値が想定の範囲か(マイナスや空でないか、選択肢のどれかか)」を、機械で確かめます。スキーマ検証のライブラリ(決めた形に合っているかを自動でチェックする道具)を使うと、この確認を一括でかけられて楽です。
- 想定外のキーはどう扱うか決めておく:頼んでいないキーが増えていたとき、無視するのか、警告を出すのか、あらかじめ方針を決めます。黙って使うと、後で「なぜこの値が入っているのか」と追う羽目になります。
検証は、AIの出力を疑うためではなく、業務データを守るための作業です。AIに書き戻す前に人の確認を挟む設計は人の確認を挟むAIワークフロー|HITLの組み方、もっともらしい誤りの見抜き方はAIのハルシネーションの見抜き方も合わせてどうぞ。
③ 崩れたとき——落とさずに立て直す
検証で「これは崩れている」と分かったら、いきなりエラーで倒すのではなく、段階を踏んで立て直します。順番はこうです。
- まず軽い救済を試す:よくある崩れは、機械的に直せます。前後の余計な文をそぎ落とす、
`の囲みを外す、最初の{から対応する}までを取り出す——このくらいの「掃除」で通ることは多いです。ただし、やりすぎて意味を変えない範囲にとどめます。 - ダメなら、もう一度だけ頼む:救済で直らなければ、AIに「さっきの出力はJSONとして読めなかった。前置きや囲みを付けず、JSONだけでもう一度返して」と1回だけ再依頼します。崩れた出力を見せて「この形で直して」と頼むのも有効です。ここで無限に繰り返さないのが肝心。リトライの回数と間隔の決め方はAI出力が不安定なときのフォールバック設計|リトライの型に整理しています。
- それでもダメなら、安全側に倒す:再依頼でも崩れるなら、あらかじめ決めた既定値を使う/その1件だけ処理を保留してエラー通知を出す、といった安全な逃げ道に切り替えます。大事なのは、1件の崩れで全体を止めないことと、崩れたことを記録に残して後から気づけることです。黙って既定値を使うと、崩れていたことに誰も気づけません。
この3段を用意しておくと、「たまに崩れる」が「たまに静かに立て直す」に変わります。利用者から見れば、いつもどおり動いているように見える。それが、業務システムに組み込むうえでの安心につながります。
明日からやること(まずこの3つ)
大がかりな作り込みは要りません。まずこの3つだけ。
- 受け取ったJSONを、パースと検証に通す:
try/catchで包み、必須項目と型を1回チェックしてから業務処理に渡す。信じてそのまま使うのをやめる。ここが一番効きます。 - 使っているモデルに「構造化出力/JSONモード」があるか、公式ドキュメントで確認する:あるなら切り替える。無いなら、プロンプトに「JSONだけ返す・前置きや囲みは付けない・この形で」と例付きで書く。
- 崩れたときの逃げ道を1本だけ用意する:「1回だけ再依頼 → それでもダメなら既定値+記録」を決めておく。無限リトライにしない。
この3つは、いちど作れば使い回せます。本番で「たまに落ちる」を追いかけることを思えば、ずっと軽い。 全部を毎回きっちりやらなくても、「受け取ったら検証する」から始めれば十分です。
AIのJSON出力を安定させるチェックリスト
組み込む前・出す前に、さっと確認します。全部に○が要るわけではなく、その機能で気になる所だけで十分です。
① 出す前(崩れにくく出させる)
- モデルの「構造化出力/JSONモード/ツール呼び出し」を使えるか確認したか
- 使えないなら、「JSONだけ・前置きや囲みなし」と指示に明記したか
- 期待する形のサンプル(例)を1つ渡しているか
- 一度に返させる件数を欲張っていないか(途中で切れないか)
② 受け取った直後(検証する)
- パースを
try/catchで包み、失敗しても全体を止めない形か - 必須項目の有無・型・値の範囲を機械でチェックしているか
- 想定外のキーが増えたときの扱いを決めているか
③ 崩れたとき(立て直す)
- 囲み除去などの軽い救済を先に試すか
- 直らないとき、再依頼は回数を決めているか(無限にしない)
- 最後は安全な既定値かエラー通知に倒し、崩れを記録しているか
この記事のまとめ
AIの構造化出力は、たいていきれいに返ってきます。 それでも、「たまに崩れる」を前提に受け皿を作っておくだけで、本番で効いてくる事故がずいぶん減ります。全部を完璧に崩れさせる必要はありません——というより、それは無理です。だからこそ、出す前に型で縛り、受け取ったら検証し、崩れたら静かに立て直す。この3層を用意しておくのが、いちばん確実で安上がりな守り方です。まずは「受け取ったら一度検証する」の一手からで十分です。

AIの出力は、いつもきれいとは限らない——だからこそ、崩れても静かに立て直せる受け皿が効きます。 今日、「受け取ったJSONを一度検証に通せた」なら、それはもう将来の自分を助ける一手です。出力が不安定なときの立て直しはAI出力が不安定なときのフォールバック設計|リトライの型、人の確認の挟み方は人の確認を挟むAIワークフロー|HITLの組み方も、必要なときにのぞいてみてください。