OpenAI Structured Outputs vs Gemini Structured Output:2026 JSON Schema API 完整对比

OpenAI Structured Outputs 与 Gemini Structured Output 并排对照:2026 API 字段、JSON Schema 子集、strict 模式、Python 示例、同 Schema 跨厂商复用与迁移清单。

本系列前几篇分别讲了Structured Output 通用落地、Gemini 一家的配置,以及Tool Calling 参数校验。如果你同时接 OpenAI 与 Google Gemini,最常被问的是:两家 Structured Output 到底差在哪?同一份 JSON Schema 能不能原样复用?

2026 年两家都已把 JSON Schema 约束解码(constrained decoding)做成一等公民,但请求字段名、Schema 子集、strict 语义、SDK 形态并不相同。本文按「概念对齐 → API 对照 → Schema 兼容性 → 代码示例 → 选型与迁移」给出完整对比,方便你在多模型 Agent 里写一份 Schema、两处调用。

概念对齐:Structured Outputs 与 Structured Output

名称上只差一个 s,含义却常被混用:

  • OpenAI Structured Outputs(复数):Chat Completions / Responses API 里 response_format: { type: "json_schema", ... } 的能力品牌名;2024 年 8 月起在 gpt-4o-2024-08-06 及之后模型上 GA,2026 年仍是 OpenAI 生产抽取的主路径。
  • Gemini Structured Output(单数):Google 文档对「MIME + Schema 约束生成」的统称;对应 responseMimeType: application/json 加 responseJsonSchema 或 SDK response_schema。

两者共同目标:让模型最终答复(不是 tool arguments)符合 JSON Schema,在 token 生成阶段就排除非法 JSON 路径。与 JSON Mode(只保证合法 JSON、不保证形状)相比,都是 L3 级硬约束——详见《从 Prompt 到 Structured Output》的四层模型。

都不替代 Tool Calling:Structured Output 管「给用户/下游程序的 JSON」;Tool Calling 管「工具参数 JSON」——见《数据流》。

2026 API 字段对照表

下面以「抽取一张发票 object」为例,对比最常用配置位(REST / SDK 概念层,具体 path 以各厂商当前文档为准):

维度OpenAIGemini
仅 JSON Moderesponse_format: { "type": "json_object" }responseMimeType: "application/json"(无 Schema)
Structured + Schemaresponse_format: { "type": "json_schema", "json_schema": { "name", "schema", "strict": true } }MIME + responseJsonSchema(REST)或 response_json_schema / response_schema(SDK)
Schema 来源标准 JSON Schema 字典;strict: true 时子集更严标准 JSON Schema(responseJsonSchema)或 OpenAPI 3.0 子集(旧 responseSchema)
解析入口message.content 字符串 → JSON.parse;部分 SDK 有 parsedresponse.text;Python google-genai 可 response.parsed(Pydantic)
推荐模型(2026)gpt-4o、gpt-4.1 系列gemini-2.5-flash、gemini-3.7-flash 等 2.5+ / 3.x
枚举分类旁路Schema 内 enum另支持 responseMimeType: text/x.enum(只输出枚举字符串)

迁移时不要交叉粘贴 OpenAPI 3.0 大写类型与 JSON Schema 小写类型:Gemini 旧 responseSchema 用 OBJECT / STRING;OpenAI 与 Gemini 新 JSON Schema 通道都用 object / string。

JSON Schema 子集与 strict 差异

两家都支持约束解码,但接受的 Schema 关键字集合不同。写跨厂商 Schema 时应取交集:

关键字 / 行为OpenAI(strict: true)Gemini(responseJsonSchema)
type / properties / required✓ 必需模式✓
enum、minimum / maximum✓✓(以文档当前列表为准)
additionalProperties: falsestrict 下所有 object 建议显式 false✓ 推荐,防模型发明字段
anyOf / oneOfstrict 下受限,宜简化支持有限,复杂 union 易失败
$ref 深度strict 要求可 inline 展开过深嵌套可能被拒,宜写扁
字段顺序不保证与 Schema 一致2.5+ 尽量保持 Schema 字段顺序
语义保证结构不保证事实正确同左;均需二次校验

OpenAI strict: true 的额外含义:Schema 必须满足更严格的子集(例如每个 object 声明 additionalProperties: false,required 覆盖全部 properties 等),否则 API 可能直接 400。Gemini 没有同名开关,但实践中同样推荐「扁平 object + 禁额外字段」——与《JSON Schema Contract》里的 Agent 最佳实践一致。

无论哪家,生产环境都要用同一份 Schema 再跑 ajv / jsonschema / Pydantic——约束解码降语法错误,不替你做业务断言。

OpenAI Structured Outputs 完整示例

用 Pydantic 导出 Schema,strict: true 开启 Structured Outputs(2026 主流写法):

from openai import OpenAI
from pydantic import BaseModel, Field

client = OpenAI()

class LineItem(BaseModel):
    name: str
    qty: int = Field(ge=1)
    unit_price_cents: int = Field(ge=0)

class Invoice(BaseModel):
    vendor: str
    currency: str = Field(description="ISO 4217, e.g. CNY")
    items: list[LineItem]
    total_cents: int

schema = Invoice.model_json_schema()
# strict 建议:根与嵌套 object 均 additionalProperties: false
schema["additionalProperties"] = False
for prop in schema.get("properties", {}).values():
    if isinstance(prop, dict) and prop.get("type") == "object":
        prop["additionalProperties"] = False

response = client.chat.completions.create(
    model="gpt-4o-2024-08-06",
    messages=[{
        "role": "user",
        "content": "从文本抽取发票:Acme 售出 2 个键盘,共 39800 分。",
    }],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "invoice",
            "strict": True,
            "schema": schema,
        },
    },
)

import json
invoice = json.loads(response.choices[0].message.content)

要点:json_object 只开 JSON Mode;要带 Schema 必须 type: json_schema。name 用于日志与多 Schema 场景。若 400,先检查 strict 子集(缺 additionalProperties、required 不完整等)。

Gemini Structured Output 完整示例

同一 Invoice 模型,用 google-genai SDK(2026 推荐):

from google import genai
from google.genai import types
from pydantic import BaseModel, Field

client = genai.Client()

class LineItem(BaseModel):
    name: str
    qty: int = Field(ge=1)
    unit_price_cents: int = Field(ge=0)

class Invoice(BaseModel):
    vendor: str
    currency: str
    items: list[LineItem]
    total_cents: int

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="从文本抽取发票:Acme 售出 2 个键盘,共 39800 分。",
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=Invoice,  # 或 response_json_schema=Invoice.model_json_schema()
    ),
)

invoice = response.parsed  # Pydantic 实例
# 无 parsed 时:json.loads(response.text)

REST 等价体在 generationConfig 里设 responseMimeType + responseJsonSchema。需要完整 Draft 关键字时用 response_json_schema;简单对象用 Pydantic response_schema 更省事。Gemini 3.7 Flash 等新模型字段相同,只换 model——见《3.7 Flash 介绍》。

同一份 Schema 如何跨厂商复用

推荐仓库结构:

schemas/
  invoice.v1.json          # 单一 JSON Schema 源
  samples/
    invoice.valid.json
    invoice.missing_vendor.json

# Python 共享层
from pathlib import Path
import json
schema = json.loads(Path("schemas/invoice.v1.json").read_text())

# OpenAI 包装
openai_body = {"type": "json_schema", "json_schema": {"name": "invoice", "strict": True, "schema": schema}}

# Gemini 包装
gemini_config = {"response_mime_type": "application/json", "response_json_schema": schema}

跨厂商适配三步:

  1. 取交集关键字:只用 type、properties、required、enum、基本 minimum/maximum;避免复杂 oneOf。
  2. OpenAI strict 预处理:脚本为每个 object 补 additionalProperties: false 与完整 required。
  3. CI 双端采样:同一样本对 OpenAI 与 Gemini 各跑一次(或 mock),用同一 ajv 校验输出——与 Tool Schema 的样例驱动测试相同思路。

本地开发:把 Schema 与模型输出贴进 JSON 工具箱做 Diff,不上传服务器。

选型:什么时候用 OpenAI、什么时候用 Gemini

场景更常见选择原因
已有 OpenAI Agent 栈(Assistants / Responses)OpenAI Structured Outputs与 tools、evals、现有 SDK 一体
多模态长文档 + JSON 抽取Gemini 2.5+ / 3.x百万 token 上下文、PDF/视频输入与 Structured Output 同请求
字段顺序敏感(CSV/表格对齐)Gemini 2.5+官方强调 Schema 字段顺序保留
强 strict 契约、禁额外字段OpenAI strict: true子集明确,违规直接拒请求
纯枚举分类(无 JSON 对象)Gemini text/x.enum比包一层单字段 object 更省 token
双云 / 降级共享 Schema + 双适配器一家限流切另一家,Schema 版本不变

2026 年许多团队并非二选一,而是同 Schema、双 Provider:抽取层抽象成 generate_structured(prompt, schema) -> dict,内部按配置路由 OpenAI 或 Gemini。

从单厂商迁移到双厂商的检查清单

  • Schema 是否已从 OpenAPI 3.0 大写类型迁到 JSON Schema 小写?
  • OpenAI 侧是否满足 strict: true 子集(additionalProperties、required)?
  • Gemini 是否使用 responseJsonSchema 而非仅 application/json?
  • 是否区分 Structured Output(最终 JSON)与 Tool Calling(arguments)两套 Schema?
  • 运行时是否对两家输出做同一份 jsonschema 二次校验?
  • Prompt 是否仍要求 markdown 围栏?(应删掉——Structured Output 不需要 ```json)
  • 日志是否记录 schema 版本号,便于 A/B 与回滚?

常见问题 FAQ

OpenAI Structured Outputs 和 Gemini Structured Output 是同一套 API 吗?

不是。概念都是「JSON Schema 约束的最终答复」,但 OpenAI 用 response_format.json_schema + strict,Gemini 用 responseMimeType + responseJsonSchema(或 SDK response_schema)。Schema 本体可共享,请求包装层需分别写。

同一份 Pydantic 模型能直接给两家吗?

可以。model_json_schema() 导出后,OpenAI 需按 strict 规则补 additionalProperties 与 required;Gemini 可直接 response_json_schema 或 response_schema=Model。先在 CI 用样例跑通两家再上线。

哪家 Schema 支持更「全」?

都不保证完整 JSON Schema Draft。OpenAI strict 子集文档化最细;Gemini 对 JSON Schema 的支持在 2.5 后明显增强但仍宜写扁。跨厂商应取交集,而不是用满 Draft 2020-12。

JSON Mode 和 Structured Output 在两家分别怎么开?

OpenAI:json_object vs json_schema。Gemini:仅 application/json vs JSON + Schema。只开 JSON Mode 时两家都只保证语法 JSON,不保证字段形状。

还需要自己做 JSON 校验吗?

需要。两家约束解码都主要保证结构与类型,不保证业务正确或事实真实。应用层应用同一份 Schema 再校验,失败则重试或人工。

和 Tool Calling 的 Schema 能混用吗?

定义层可共用 Pydantic/Zod 生成器,但调用层分开:Structured Output 绑在 response_format / generationConfig;Tool Calling 绑在 tools[].parameters 或 MCP inputSchema。勿用 Structured Output 假装已执行工具。

总结

2026 年 OpenAI Structured Outputs 与 Gemini Structured Output 已是同一问题的两种厂商实现:都用 JSON Schema 在解码阶段锁形状,都比 JSON Mode 硬一层。差异在 API 字段、strict 子集、SDK 解析入口与多模态/上下文等工程细节。

实践路径:一份 Schema 源 → OpenAI strict 预处理 → Gemini responseJsonSchema → 统一运行时校验。先用 JSON 工具箱本地对照 Schema 与样例输出,再接入双 Provider 降级。