Gemini APIのJSON崩れを絶対に許さない:3段構えのパース戦略

この記事は、Growth Lab編集部 が Gemini API / JSON / Error Handling の観点から検証結果を整理したものです。
読了前に全体像を掴み、その後に目次から必要な節へ進める構成を想定しています。
目次を表示
TL;DR
- LLM は「JSON を返さない」前提で組むのが、自動化の鉄則
- Direct Parse / Code Block / Regex Extraction の 3 段構えで救出
- 指示を守らせる努力と、守らなかった時の保険を両立させる
The Pain: "Here is the JSON"
LLM(GeminiやChatGPT)に return JSON only と指示しても、彼らは親切心から余計なことをします。
"Sure, here is the JSON you requested:\n
json\n{ ... }\n"
これをそのまま JSON.parse() に投げると、当然ながら SyntaxError で落ちます。
また、Markdownのコードブロック記法(```json)が含まれていたり、謎の接頭辞がついていることも日常茶飯事です。
The Solution: 3段構えのパース (Triple-Layer Parsing)
LLMの出力は「汚染されている」という前提に立ち、3段階のフィルタで救出を試みます。
- Direct Parse: そのままパース(奇跡的に綺麗な場合)。
- Code Block Extraction: マークダウン記法(```)の中身を取り出してパース。
- Regex Extraction: 文字列中の最初の
{から最後の}までを正規表現で無理やり切り出してパース。
これでもダメなら諦めますが、99%はこの網にかかります。
The Implementation: 実際のコード
scripts/generate_gemini.mjs で実際に稼働しているコードです。
function parseJsonFromGeminiText(text) {
if (!text) throw new Error("Empty response text");
// Strategy 1: 素直にパース
try {
return JSON.parse(text);
} catch {}
// Strategy 2: Code Block (```json ... ```) から抽出
const jsonCodeBlockMatch = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
if (jsonCodeBlockMatch) {
try {
return JSON.parse(jsonCodeBlockMatch[1].trim());
} catch (e) {
console.warn("Failed to parse from code block");
}
}
// Strategy 3: Brute Force ({ ... }) 抽出
// 最初の '{' と 最後の '}' を見つける
const jsonMatch = text.match(/\{[\s\S]*\}/);
if (jsonMatch) {
try {
return JSON.parse(jsonMatch[0]);
} catch (e) {
console.warn("Failed to parse from fallback extraction");
}
}
throw new Error("JSON parse failed: " + text.slice(0, 100) + "...");
}
プロンプト側での工夫
もちろん、まずプロンプトで釘を刺すことも重要です。
const prompt = `
...
【出力形式】
必ずJSON形式のみで出力してください。
Markdownのコードブロック(\`\`\`)や、"Here is..." などの説明文は一切含めないでください。
{ で始まり } で終わる有効なJSON文字列のみを出力してください。
...
`;
しかし、LLMは確率モデルである以上、指示を無視する可能性はゼロになりません。「指示を守らせる努力」と「守らなかった時の保険」の両方が必要です。
The Takeaway: 完璧な入力などない
Web APIの世界では「入力値検証(Validation)」は基本ですが、AIエンジニアリングの世界でもそれは同じです。むしろ、相手が人間(ユーザー)よりも「賢いが気まぐれな存在(LLM)」である分、より柔軟で粘り強いパースロジックが求められます。
次回は、これらスクリプトを定期実行するためのインフラ「GitHub Actions」について解説します。
パース戦略の比較表
| レイヤー | 手法 | 対象 | 成功率 |
| :---------- | :----------- | :------------- | :----- |
| Layer 1 | Direct Parse | 完璧な JSON | 低 |
| Layer 2 | Code Block | json ... | 中 |
| Layer 3 | Regex | { ... } 抽出 | 高 |
References
Growth Lab編集部
Gemini API / JSON / Error Handling
AIエージェント開発、記事制作フロー、デザインシステム運用の接続を実装ベースで検証し、再現可能な手順へ落とし込むことを目的に運営しています。
あわせて読む
同じテーマや近い文脈の記事を続けて読めるようにする。
継続接点
更新を追いかける
新着記事、特集、検証ログをまとめて追える入口として使う。メール購読導線の本実装前でも、継続接点を切らさない。
- 新着記事をまとめて確認できる
- 関連記事や特集ページへつながる
- 実験ログを継続的に追える
本実装ではメール購読や通知機能へ差し替え可能。