教程
AI 生成 JSON 爲什麼還是會出錯?2026 Structured Output、JSON Schema 與 Validation 完整指南
團隊上了 json_schema + strict,CI 仍紅。原因通常不是「模型又胡來了」,而是把 Structured Output 當成萬能保險——它鎖得住鍵名和類型,鎖不住分類對錯、數值真實和截斷後的殘 JSON。
把大模型接到訂單抽取、風控打標或 Agent 工具參數裏,JSON 出錯是常態而不是例外。2026 年主流棧已經提供 Structured Output:OpenAI 的 json_schema + strict、Gemini 的 responseSchema、Anthropic 的 output_config.format、Apple 的 @Generable——它們比「請只返回 JSON」可靠一個數量級,但工程事故仍頻繁發生。差別在於:很多失敗發生在 Structured Output 的保障範圍之外,或者 Schema 本身不可被該模型編譯,或者校驗鏈只做了 JSON.parse 就入庫。這篇按「爲什麼還會錯」組織,把 2026 能力邊界、Schema 寫法與本地 Validation 串成一條可落地的排查路徑,並接上站內 Structured Output、Gemini、DeepSeek 與 MCP 相關文章。
Structured Output 解決了什麼、沒解決什麼
先對齊預期。Structured Output(或各家的 JSON Schema 模式)在解碼階段限制下一 token 的合法集合,因此輸出大概率同時滿足:可被 JSON.parse 的語法;鍵名、必填、類型、枚舉與 additionalProperties 等 Schema 聲明的形狀。OpenAI 文檔把這一點與 JSON mode 明確區分:後者只保證 JSON 語法,前者保證你的 Schema。
它不能保證:分類標籤在業務上是否正確;金額是否與原文一致;長數組是否因 max_tokens 被截斷成半截對象;Tool arguments 執行後外部 API 是否成功。第三層語義與第四層工程仍 100% 是你的代碼負責。團隊裏常見的挫敗感來自「明明開了 strict 爲什麼還錯」——錯的可能根本不是形狀層,而是把語義失敗當成 Schema 失敗去調 prompt。
另一個誤區是把 Tool Calling 的 arguments JSON 與最終答覆的 Structured Output 混爲一談。MCP tools/call、OpenAI function.arguments、DeepSeek strict tools 都涉及 JSON 字符串,但約束髮生在不同 hop:有的只有 json_object,有的 Beta strict 只覆蓋參數 Schema 子集。需要分 hop 看保障級別,而不是假設「全鏈路 Schema 化」。
四層錯誤:語法、形狀、語義、工程
用四層 taxonomy 定位失敗,比籠統說「JSON 壞了」更快:
| 層級 | 典型症狀 | Structured Output 能否防 |
|---|---|---|
| 語法 | JSON.parse 拋錯、尾逗號、截斷字符串 | JSON mode / Schema 模式大多能防;token 不足時仍可能截斷 |
| 形狀 | 缺鍵、錯類型、enum 外取值、多餘字段 | json_schema + strict 可防;Schema 超子集或 strict 未開則不行 |
| 語義 | 字段齊但分類錯、幻覺 ID、與源文本矛盾 | 不能;需抽檢、雙模型、規則引擎或檢索 grounding |
| 工程 | 雙 parse、編碼 BOM、流式拼接丟括號、緩存舊 Schema | 不能;需統一校驗入口與版本化 Schema |
語法層失敗最好查:是否仍走純 prompt;是否 max_tokens 過小;是否從 markdown 代碼塊裏 regex 摳 JSON 而不是拿 API 的 structured 字段。形狀層失敗先查:strict 是否 true;required 是否列全所有鍵(OpenAI strict 要求);是否用了該模型不支持的 Schema 關鍵字。
語義層失敗應接受「Schema 校驗通過 ≠ 可入庫」。工程上常見做法:Schema 校驗作爲 hard gate;業務規則(範圍、外鍵存在性、與輸入 hash 對比)作爲 second gate;高風險場景人工或二次模型審覈。
2026 各家 API 實際保證什麼
2026 年沒有「一個 Schema 走天下」,只有「按供應商文檔選子集」。下面這張表是工程選型用的粗粒度對照,細節以各文檔爲準:
| 供應商 / 模式 | 配置入口 | 實際保證 |
|---|---|---|
| OpenAI json_schema + strict | response_format 或 Responses text.format | 形狀 + 類型 + 必填;refusal 字段可表示拒答 |
| Gemini responseSchema | generationConfig.responseSchema | JSON 語法 + Schema 字段;關鍵字子集與 OpenAI 略有差異 |
| DeepSeek json_object | response_format.type = json_object | 語法 JSON;形狀靠 prompt + 本地校驗 |
| Tool arguments strict (Beta) | tools[].strict 或各家等價開關 | 參數 JSON 形狀;Beta 子集限制 |
OpenAI 在 2026 年把 Structured Output 作爲 Responses API 一等公民:Assistants sunset 後,json_schema 掛在 text.format 下,規則與 Chat Completions 相同。遷移時 Schema 本體可複用,變的是外殼字段——見Assistants → Responses 遷移文。Gemini 側 responseJsonSchema 與 property ordering 更新見Gemini API JSON 輸出教程。DeepSeek V4-Flash 仍停在 json_object,見DeepSeek V4-Flash JSON 文。
Apple 生態用 @Generable 在 Swift 側做結構化,落地到 HTTP 或持久化前仍要 encode 成 JSON 再校驗。Agent 工具鏈路上,Remote MCP 協議 JSON 的無狀態化不替代 arguments 校驗——見Stateless MCP 解析。
JSON Schema 寫給模型看的五條規則
Schema 既是文檔也是編譯輸入。寫給模型時與寫給人類 REST API 文檔的側重點不同:
- 扁平優先:深度嵌套與大量 $ref 增加編譯失敗率;能扁平的對象就扁平,重複結構用 $defs 但控制深度。
- additionalProperties: false 與 required 列全:OpenAI strict 下 object 的所有 properties 鍵都要出現在 required 裏,否則模型可能合法地省略你「以爲默認」的字段。
- 用 description 寫清枚舉語義:enum 只限製取值,description 幫助模型在邊界 case 選對值;不要把業務規則只寫在 prompt 裏而 Schema 裏空着。
- 慎用 oneOf 大矩陣:多分支聯合體是常見編譯失敗源;能拆成多次調用或頂層 category + 子 Schema 就不要一個巨型 oneOf。
- 與本地校驗器共用同一份 Schema:CI、運行時、JSONVue 手動排查應 pin 同一 JSON 文件,避免「線上 strict 用 A、本地校驗用 B」。
官方 JSON Schema 教程見Understanding JSON Schema。注意「規範允許的關鍵字」與「某模型 API 實際支持的關鍵字」不是同一集合——集成測試應包含故意違規樣本,而不只 happy path。
站內AI Structured Output 教程從 OpenAI json_schema 示例出發;本篇補的是失敗模式與校驗鏈,不重複 SDK 字段名清單。
Validation 流水線:parse → Schema → 業務
推薦固定三步,任何 hop(模型最終答覆、Tool arguments、MCP 結果)都走同一套:
- Parse:JSON.parse 或等效;失敗則記錄 raw text、請求 id、模型版本,不要 silent retry 改字符串(易掩蓋截斷)。
- Schema:用 Draft 2020-12 或供應商要求的 dialect 校驗;失敗則輸出 path 與 keyword,方便和 JSON Diff 對照預期 fixture。
- 業務:自定義規則——數值範圍、跨字段一致、與源文檔對齊、外鍵存在——這一步捕獲語義錯誤。
Antidote 文檔把 Structured Outputs 描述爲減少格式錯誤;社區實踐仍強調 client-side validation,因爲供應商也明示 Schema 子集與拒答場景。把校驗放在網關統一做,比在每個 Agent 分支裏 copy paste 更不易 drift。
版本化 Schema:Breaking 改字段時 bump schema_version 或 tool 名,避免客戶端緩存舊 Tool 列表(MCP 文裏強調過 stale cache 會把錯誤 shape 寫進 arguments)。響應用 metadata 帶回 schema_version,便於日誌聚合「哪版 Schema 開始失敗率上升」。
排查清單與 JSONVue 實操
線上 JSON 報錯時按順序過一遍:
- 確認 hop:是最終 structured 字段、message.content 還是 tool_calls[].function.arguments?
- 看 token:finish_reason 是否 length;JSON 模式是否從中間截斷。
- 對照 strict 與 Schema 文件:required 是否齊全;是否用了不支持的關鍵字。
- 準備三份 fixture:valid、missing-field、wrong-enum,在 CI 裏對同一 Schema 跑校驗。
- 語義抽檢:Schema 過仍隨機人工或規則複覈,尤其金融、醫療、權限類字段。
JSONVue 適合在中間步驟人工復現:把 raw 響應貼進JSON 格式化看 parse 是否過;把 Schema 與實例貼進JSON Schema 校驗看 shape 哪條失敗;預期 vs 實際用JSON Diff對比鍵級差異。Agent 集成裏可把這三步當作 on-call 手順,比直接改 prompt 省時間。
若錯誤只在某一供應商出現,先縮小是 Schema 編譯問題還是模型行爲:同一 Schema 換 OpenAI strict 與 Gemini responseSchema 各跑一次,Diff 結果若 shape 一致而僅 enum 不同,多半是語義層或 description 不足,而不是解析器 bug。
延伸閱讀:AI Structured Output 教程、Gemini API JSON 輸出、DeepSeek V4-Flash JSON、Assistants → Responses 遷移。
常見問題 FAQ
開了 strict 爲什麼 Schema 校驗還失敗?
常見原因:本地校驗 Schema 與請求裏 Schema 不一致;strict 未 true;required 未列全 properties;或使用了該 API 不支持的 keyword。先用同一份文件在 JSONVue 校驗通過,再對照請求體。
Structured Output 能替代 JSON Schema 校驗嗎?
不能替代。Structured Output 在模型側提高形狀合規概率;本地校驗防供應商變更、防截斷、防非模型 hop 的 JSON,並承載業務規則。兩層疊加才穩。
json_object 和 json_schema 怎麼選?
要固定字段、類型、枚舉走 json_schema + strict;只要求合法 JSON、字段可漂移時用 json_object 並必須本地 Schema。DeepSeek 等僅支持 json_object 的棧只能後者。
Tool arguments 誰校驗?
模型側可能有 strict Beta;執行層必須 JSON.parse 後再 Schema 校驗,再調真實 API。MCP tools/call 同理——協議無狀態不等於參數自動正確。
總結與下一步
AI 生成 JSON 在 2026 年仍出錯,因爲 Structured Output 只覆蓋語法與形狀,語義與工程層仍依賴你;且各 API 支持的關鍵字與 strict 語義不同,Schema 寫得太滿會編譯失敗,寫得太鬆則形狀漂移。用四層 taxonomy 定位問題,用 parse → Schema → 業務三步校驗入庫,用版本化 Schema 與 fixture 防迴歸。
下一步:選一條生產失敗樣本,在 JSONVue 走格式化、Schema 校驗與 Diff;對照本篇清單看落在哪一層。需要 API 接入細節時閱讀 Structured Output 基礎教程、Gemini JSON 輸出、DeepSeek V4-Flash 與 Assistants 遷移文;需要 Agent 工具參數鏈路時閱讀 Stateless MCP 解析。