Gemini structured outputs (JSON / enum / XML / YAML)
Status: DOCUMENTED + LIVE_VERIFIED (14 probes on gemini-3.5-flash-lite, 2026-09-18). The new responseFormat field is LIVE_VERIFIED; responseSchema / responseJsonSchema / responseMimeType are marked deprecated in the discovery document but still work.
Sources: https://ai.google.dev/gemini-api/docs/generate-content/structured-output · https://ai.google.dev/api/generate-content#generationconfig · discovery GenerationConfig, Schema, ResponseFormatConfig, TextResponseFormat
Machine-readable: generated/fragments/parameters/gemini-generate-content.json (generationConfig.response*), generated/fragments/streaming-events/gemini-core.json#structured_output_chunks
Last verified: 2026-09-18
1. Three ways to ask for structure
| Form | Field(s) | Schema dialect | Status | Live |
|---|---|---|---|---|
| New (docs today) | generationConfig.responseFormat.text = {mimeType, schema} |
JSON Schema | DOCUMENTED, LIVE_VERIFIED | {"mimeType": "APPLICATION_JSON", "schema": {...}} → {"ok": true}. Wire enum is APPLICATION_JSON | TEXT_PLAIN; the docs' "application/json" string → 400 Invalid value at 'generation_config.response_format.text.mime_type' (…TextResponseFormat.MimeType) (the SDKs translate it). |
| JSON Schema (legacy) | responseMimeType: "application/json" + responseJsonSchema |
JSON Schema subset | DOCUMENTED (deprecated in discovery), LIVE_VERIFIED | {"ok": true, "word": "OK"}; works even without responseMimeType (docs say required — not enforced). |
| OpenAPI Schema (legacy) | responseMimeType + responseSchema |
Schema proto (typed enums OBJECT, STRING…) |
DOCUMENTED (deprecated), LIVE_VERIFIED | {"word": "OK", "ok": true} — propertyOrdering: ["word","ok"] honoured. Silently ignored without responseMimeType. Unknown keyword (additionalProperties) → 400 Unknown name "additionalProperties" at 'generation_config.response_schema'. |
| JSON mode, no schema | responseMimeType: "application/json" |
— | LIVE_VERIFIED | {"ok": true} |
| Enum mode | responseMimeType: "text/x.enum" + responseSchema {type: STRING, enum: [...]} |
— | LIVE_VERIFIED | returns exactly OK (1 token) |
| XML / YAML | responseMimeType: "application/xml" | "application/yaml" |
— | LIVE_VERIFIED (xml) | <response>\n <ok>true</ok>… — undocumented in guides, listed in the 400 text: allowed mimetypes are text/plain, application/json, application/xml, application/yaml and text/x.enum |
Combinations: responseFormat.text + responseMimeType together → 200 JSON. responseSchema + responseJsonSchema together → 200 but both ignored, plain prose returned (docs say it must be an error — it is not). responseMimeType: text/html → 400.
2. Supported JSON Schema keywords (responseJsonSchema / responseFormat.text.schema)
From the discovery description: $id, $defs, $ref, $anchor, type (incl. arrays like ["string","null"]), format, title, description, enum (strings and numbers), items, prefixItems, minItems, maxItems, minimum, maximum, anyOf, oneOf (treated as anyOf), properties, additionalProperties, required, plus non-standard propertyOrdering. The guide adds format: date-time|date|time for strings. Cyclic $ref allowed only inside non-required properties; a sub-schema with $ref may only carry $-prefixed siblings. Unsupported keywords are ignored (minLength accepted silently). Verified: $defs + $ref + anyOf [ref, {type: null}] → 200.
3. Schema (OpenAPI subset for responseSchema)
Fields: type (STRING|NUMBER|INTEGER|BOOLEAN|ARRAY|OBJECT|NULL), format, title, description, nullable, enum[], items, properties, required[], propertyOrdering[], minItems, maxItems, minimum, maximum, minLength, maxLength, pattern, anyOf[], minProperties, maxProperties, default (ignored), example. Anything else → 400. Gemini 2.0 needed explicit propertyOrdering; Gemini 3.x outputs keys in schema order (verified: word before ok).
4. Behaviour and limits
- Output is a syntactically valid instance of the schema; values are not validated semantically — validate client-side (docs).
- Very large / deeply nested schemas may be rejected — shorten names, reduce nesting.
maxOutputTokenstruncates JSON mid-way (finishReason: MAX_TOKENS,{"ok": true, "word": "OKobserved with 32 tokens) — budget generously.- Streaming: chunks are partial JSON strings that concatenate (3 chunks observed; final chunk carries the
thoughtSignature). - Structured outputs with built-in tools (Search, URL context, code execution, file search, function calling): preview, Gemini 3 (
gemini-3.1-pro-preview,gemini-3.8-flash) only. - Model support table (docs): 3.1 Flash-Lite, 3.1 Pro Preview, 3.5 Flash, 2.5 Pro/Flash/Flash-Lite, 2.0 Flash/Flash-Lite (with
propertyOrdering). Model cards for 3.5 Flash-Lite / 3.8 Flash also list "Structured outputs: Supported"; verified on 3.5 Flash-Lite. - Thought signatures are still attached to the JSON text part — keep them when echoing history.
5. SDK
- Python:
config={"response_format": {"text": {"mime_type": "application/json", "schema": Model.model_json_schema()}}}ortypes.GenerateContentConfig(response_mime_type="application/json", response_json_schema=..., response_schema=PydanticModel);response.parsedwhen a Pydantic class was given. - Node:
config: {responseFormat: {text: {mimeType: "application/json", schema: zodToJsonSchema(z)}}}orresponseMimeType+responseJsonSchema. - Examples:
examples/gemini/structured-output/.