OpenAI Structured Outputs vs Gemini Structured Output: 2026 JSON Schema API Comparison

Side-by-side comparison of OpenAI Structured Outputs and Gemini Structured Output — API fields, JSON Schema subsets, strict mode, code samples, cross-vendor Schema reuse, and migration checklist for 2026.

Earlier posts in this series covered Structured Output in general, Gemini-specific configuration, and Tool Calling validation. If you integrate both OpenAI and Google Gemini, the recurring question is: how do their Structured Output features differ, and can one JSON Schema be reused as-is?

In 2026 both vendors treat JSON Schema constrained decoding as a first-class feature, but request field names, Schema subsets, strict semantics, and SDK shapes differ. This article aligns concepts, compares APIs, Schema compatibility, code samples, selection, and migration so you can maintain one Schema and call two providers.

Concept alignment: Structured Outputs vs Structured Output

The names differ by one letter but are often conflated:

  • OpenAI Structured Outputs (plural): the Chat Completions / Responses API capability via response_format: { type: "json_schema", ... }; GA on gpt-4o-2024-08-06 and later, still the main OpenAI path for production extraction in 2026.
  • Gemini Structured Output (singular): Google’s term for MIME + Schema constrained generation — responseMimeType: application/json plus responseJsonSchema or SDK response_schema.

Shared goal: the model’s final reply (not tool arguments) matches JSON Schema, excluding illegal JSON paths during token generation. Both are L3 hard constraints vs JSON Mode — see the four-level model in the Prompt to Structured Output guide.

Neither replaces Tool Calling: Structured Output governs JSON for users/downstream programs; Tool Calling governs tool argument JSON — see the data-flow article.

2026 API field comparison

Invoice extraction object — conceptual REST/SDK fields (verify paths in current docs):

DimensionOpenAIGemini
JSON Mode onlyresponse_format: { "type": "json_object" }responseMimeType: "application/json" (no Schema)
Structured + Schemaresponse_format: { "type": "json_schema", "json_schema": { "name", "schema", "strict": true } }MIME + responseJsonSchema (REST) or response_json_schema / response_schema (SDK)
Schema sourceStandard JSON Schema dict; stricter subset when strict: trueStandard JSON Schema (responseJsonSchema) or OpenAPI 3.0 subset (legacy responseSchema)
Parse entrymessage.content string → JSON.parse; some SDKs expose parsedresponse.text; Python google-genai may expose response.parsed (Pydantic)
Recommended models (2026)gpt-4o, gpt-4.1 familygemini-2.5-flash, gemini-3.7-flash, other 2.5+ / 3.x
Enum-only shortcutenum inside SchemaAlso responseMimeType: text/x.enum (enum string only)

When migrating, do not mix OpenAPI 3.0 uppercase types with JSON Schema lowercase: legacy Gemini responseSchema uses OBJECT / STRING; OpenAI and Gemini JSON Schema channels use object / string.

JSON Schema subset and strict differences

Both use constrained decoding but accept different keyword sets. Cross-vendor Schemas should use the intersection:

Keyword / behaviorOpenAI (strict: true)Gemini (responseJsonSchema)
type / properties / required✓ required pattern✓
enum, minimum / maximum✓✓ (per current docs)
additionalProperties: falseexplicit false on all objects in strict✓ recommended
anyOf / oneOflimited under strict — simplifylimited support
$ref depthstrict expects inline-friendlydeep nesting may be rejected — flatten
Field ordernot guaranteed vs Schema2.5+ tries to preserve Schema order
Semantic guaranteestructure onlysame — re-validate in app

OpenAI strict: true additionally requires a documented subset (e.g. every object has additionalProperties: false, required covers all properties) or the API may return 400. Gemini has no identical flag but the same flat-object practices apply — aligned with the JSON Schema Contract article.

Either way, re-run the same Schema with ajv / jsonschema / Pydantic in production — constrained decoding reduces syntax errors, not business truth.

OpenAI Structured Outputs example

Pydantic Schema with strict: true (2026 mainstream pattern):

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()
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": "Extract invoice: Acme sold 2 keyboards, total 39800 cents.",
    }],
    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 is JSON Mode only; Schema requires type: json_schema. On 400, check strict subset (missing additionalProperties, incomplete required, etc.).

Gemini Structured Output example

Same Invoice model with google-genai (2026 recommended):

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="Extract invoice: Acme sold 2 keyboards, total 39800 cents.",
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=Invoice,
    ),
)

invoice = response.parsed
# or json.loads(response.text)

REST sets responseMimeType + responseJsonSchema in generationConfig. New models like Gemini 3.7 Flash use the same fields — see the 3.7 Flash intro.

Reusing one Schema across vendors

Recommended repo layout:

schemas/
  invoice.v1.json
  samples/
    invoice.valid.json

schema = json.loads(Path("schemas/invoice.v1.json").read_text())
openai_body = {"type": "json_schema", "json_schema": {"name": "invoice", "strict": True, "schema": schema}}
gemini_config = {"response_mime_type": "application/json", "response_json_schema": schema}

Three adaptation steps: (1) intersect keywords only; (2) OpenAI strict preprocessor for additionalProperties and required; (3) CI samples against both providers with the same ajv validator.

When to choose OpenAI vs Gemini

ScenarioCommon pickWhy
Existing OpenAI Agent stackOpenAI Structured OutputsIntegrated with tools, evals, SDK
Long multimodal docs + JSON extractGemini 2.5+ / 3.xMillion-token context, PDF/video in one request
Field order matters (CSV alignment)Gemini 2.5+Schema field order preservation
Hard strict contract, no extra fieldsOpenAI strict: trueExplicit subset, 400 on bad Schema
Enum-only classificationGemini text/x.enumLess token overhead than single-field object
Dual cloud / failoverShared Schema + two adaptersSame Schema version on provider switch

Dual-vendor migration checklist

  • Migrated Schema from OpenAPI 3.0 uppercase to JSON Schema lowercase?
  • OpenAI side satisfies strict: true subset?
  • Gemini uses responseJsonSchema, not MIME-only JSON?
  • Separated Structured Output Schema from Tool Calling Schema?
  • Same jsonschema re-validation on both outputs?
  • Removed Prompt instructions for markdown JSON fences?
  • Logs include schema version for rollback?

FAQ

Are OpenAI Structured Outputs and Gemini Structured Output the same API?

No. Same concept — JSON Schema constrained final reply — but OpenAI uses response_format.json_schema + strict; Gemini uses responseMimeType + responseJsonSchema. Share Schema bodies; write separate request wrappers.

Can one Pydantic model feed both?

Yes. Export with model_json_schema(); add OpenAI strict preprocessing; pass to Gemini as response_json_schema or response_schema=Model. CI both before production.

Which supports a “fuller” Schema?

Neither guarantees full JSON Schema Draft. OpenAI strict is best documented; Gemini improved in 2.5+ but prefer flat Schemas. Use intersection, not maximal Draft.

How do JSON Mode vs Structured Output differ on each?

OpenAI: json_object vs json_schema. Gemini: application/json only vs JSON + Schema. JSON Mode guarantees syntax only on both.

Still need app-level JSON validation?

Yes. Both mainly guarantee structure and types, not business correctness. Re-validate with the same Schema; retry or escalate on failure.

Can Tool Calling Schema be merged with Structured Output?

Share generators (Pydantic/Zod) but separate call sites: response_format / generationConfig vs tools[].parameters or MCP inputSchema. Structured Output does not execute tools.

Summary

In 2026 OpenAI Structured Outputs and Gemini Structured Output are two vendor implementations of the same idea: lock JSON shape at decode time, harder than JSON Mode. Differences are API fields, strict subsets, SDK parse paths, and engineering extras like multimodal context.

Practice path: one Schema source → OpenAI strict prep → Gemini responseJsonSchema → unified runtime validation. Validate Schema and samples locally in JSON Toolbox before dual-provider rollout.