Repository Public
1# Structured outputs23> [!NOTE]4> **Note** : This version of the page covers the new [Interactions API](https://ai.google.dev/gemini-api/docs/interactions/interactions-overview), which is currently in Beta. 5> For stable production deployments, we recommend you continue to use the `generateContent` API. You can use the toggle on this page to switch between the versions.67You can configure Gemini models to generate responses that adhere to a provided8JSON Schema. This ensures predictable, type-safe results and simplifies9extracting structured data from unstructured text.1011Using structured outputs is ideal for:1213- **Data extraction:** Pull specific information like names and dates from text.14- **Structured classification:** Classify text into predefined categories.15- **Agentic workflows:** Generate structured inputs for tools or APIs.1617In addition to supporting JSON Schema in the REST API, the Google GenAI SDKs18allow defining schemas using19[Pydantic](https://docs.pydantic.dev/latest/) (Python) and20[Zod](https://zod.dev/) (JavaScript).2122## Structured output examples2324### Recipe Extractor2526This example demonstrates how to extract structured data from text using basic27JSON Schema types like `object`, `array`, `string`, and `integer`.2829### Python3031 from google import genai32 from pydantic import BaseModel, Field33 from typing import List, Optional3435 class Ingredient(BaseModel):36 name: str = Field(description="Name of the ingredient.")37 quantity: str = Field(description="Quantity of the ingredient, including units.")3839 class Recipe(BaseModel):40 recipe_name: str = Field(description="The name of the recipe.")41 prep_time_minutes: Optional[int] = Field(description="Optional time in minutes to prepare the recipe.")42 ingredients: List[Ingredient]43 instructions: List[str]4445 client = genai.Client()4647 prompt = """48 Please extract the recipe from the following text.49 The user wants to make delicious chocolate chip cookies.50 They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,51 1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,52 3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.53 For the best part, they'll need 2 cups of semisweet chocolate chips.54 First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,55 baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar56 until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry57 ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons58 onto ungreased baking sheets and bake for 9 to 11 minutes.59 """6061 interaction = client.interactions.create(62 model="gemini-3.5-flash",63 input=prompt,64 response_format={65 "type": "text",66 "mime_type": "application/json",67 "schema": Recipe.model_json_schema()68 },69 )7071 recipe = Recipe.model_validate_json(interaction.output_text)72 print(recipe)7374### JavaScript7576 import { GoogleGenAI } from "@google/genai";77 import * as z from "zod";7879 const recipeJsonSchema = {80 type: "object",81 properties: {82 recipe_name: {83 type: "string",84 description: "The name of the recipe."85 },86 prep_time_minutes: {87 type: "integer",88 description: "Optional time in minutes to prepare the recipe."89 },90 ingredients: {91 type: "array",92 items: {93 type: "object",94 properties: {95 name: { type: "string", description: "Name of the ingredient."},96 quantity: { type: "string", description: "Quantity of the ingredient, including units."}97 },98 required: ["name", "quantity"]99 }100 },101 instructions: {102 type: "array",103 items: { type: "string" }104 }105 },106 required: ["recipe_name", "ingredients", "instructions"]107 };108109 const recipeSchema = z.fromJSONSchema(recipeJsonSchema);110111 const client = new GoogleGenAI({});112113 const prompt = `114 Please extract the recipe from the following text.115 The user wants to make delicious chocolate chip cookies.116 They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,117 1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,118 3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.119 For the best part, they'll need 2 cups of semisweet chocolate chips.120 First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,121 baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar122 until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry123 ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons124 onto ungreased baking sheets and bake for 9 to 11 minutes.125 `;126127 const interaction = await client.interactions.create({128 model: "gemini-3.5-flash",129 input: prompt,130 response_format: {131 type: 'text',132 mime_type: 'application/json',133 schema: recipeJsonSchema134 },135 });136137 const recipe = recipeSchema.parse(JSON.parse(interaction.output_text));138 console.log(recipe);139140### REST141142 curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \143 -H "x-goog-api-key: $GEMINI_API_KEY" \144 -H 'Content-Type: application/json' \145 -H "Api-Revision: 2026-05-20" \146 -d '{147 "model": "gemini-3.5-flash",148 "input": "Please extract the recipe from the following text.\nThe user wants to make delicious chocolate chip cookies.\nThey need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,\n1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,\n3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.\nFor the best part, they will need 2 cups of semisweet chocolate chips.\nFirst, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,\nbaking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar\nuntil light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry\ningredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons\nonto ungreased baking sheets and bake for 9 to 11 minutes.",149 "response_format": {150 "type": "text",151 "mime_type": "application/json",152 "schema": {153 "type": "object",154 "properties": {155 "recipe_name": {156 "type": "string",157 "description": "The name of the recipe."158 },159 "prep_time_minutes": {160 "type": "integer",161 "description": "Optional time in minutes to prepare the recipe."162 },163 "ingredients": {164 "type": "array",165 "items": {166 "type": "object",167 "properties": {168 "name": { "type": "string", "description": "Name of the ingredient."},169 "quantity": { "type": "string", "description": "Quantity of the ingredient, including units."}170 },171 "required": ["name", "quantity"]172 }173 },174 "instructions": {175 "type": "array",176 "items": { "type": "string" }177 }178 },179 "required": ["recipe_name", "ingredients", "instructions"]180 }181 }182 }183 }'184185**Example Response:**186187 {188 "recipe_name": "Delicious Chocolate Chip Cookies",189 "ingredients": [190 { "name": "all-purpose flour", "quantity": "2 and 1/4 cups" },191 { "name": "baking soda", "quantity": "1 teaspoon" },192 { "name": "salt", "quantity": "1 teaspoon" },193 { "name": "unsalted butter (softened)", "quantity": "1 cup" },194 { "name": "granulated sugar", "quantity": "3/4 cup" },195 { "name": "packed brown sugar", "quantity": "3/4 cup" },196 { "name": "vanilla extract", "quantity": "1 teaspoon" },197 { "name": "large eggs", "quantity": "2" },198 { "name": "semisweet chocolate chips", "quantity": "2 cups" }199 ],200 "instructions": [201 "Preheat the oven to 375°F (190°C).",202 "In a small bowl, whisk together the flour, baking soda, and salt.",203 "In a large bowl, cream together the butter, granulated sugar, and brown sugar until light and fluffy.",204 "Beat in the vanilla and eggs, one at a time.",205 "Gradually beat in the dry ingredients until just combined.",206 "Stir in the chocolate chips.",207 "Drop by rounded tablespoons onto ungreased baking sheets and bake for 9 to 11 minutes."208 ]209 }210211### Content Moderation212213This example showcases `anyOf` for conditional schemas and `enum` for214classification, allowing the output structure to vary based on the content.215216### Python217218 from google import genai219 from pydantic import BaseModel, Field220 from typing import Union, Literal221222 class SpamDetails(BaseModel):223 reason: str = Field(description="The reason why the content is considered spam.")224 spam_type: Literal["phishing", "scam", "unsolicited promotion", "other"] = Field(description="The type of spam.")225226 class NotSpamDetails(BaseModel):227 summary: str = Field(description="A brief summary of the content.")228 is_safe: bool = Field(description="Whether the content is safe for all audiences.")229230 class ModerationResult(BaseModel):231 decision: Union[SpamDetails, NotSpamDetails]232233 client = genai.Client()234235 prompt = """236 Please moderate the following content and provide a decision.237 Content: 'Congratulations! You''ve won a free cruise to the Bahamas. Click here to claim your prize: www.definitely-not-a-scam.com'238 """239240 interaction = client.interactions.create(241 model="gemini-3.5-flash",242 input=prompt,243 response_format={244 "type": "text",245 "mime_type": "application/json",246 "schema": ModerationResult.model_json_schema()247 },248 )249250 result = ModerationResult.model_validate_json(interaction.output_text)251 print(result)252253### JavaScript254255 import { GoogleGenAI } from "@google/genai";256 import * as z from "zod";257258 const moderationResultJsonSchema = {259 type: "object",260 properties: {261 decision: {262 anyOf: [263 {264 type: "object",265 title: "SpamDetails",266 description: "Details for content classified as spam.",267 properties: {268 reason: { type: "string", description: "The reason why the content is considered spam." },269 spam_type: { type: "string", enum: ["phishing", "scam", "unsolicited promotion", "other"], description: "The type of spam." }270 },271 required: ["reason", "spam_type"]272 },273 {274 type: "object",275 title: "NotSpamDetails",276 description: "Details for content classified as not spam.",277 properties: {278 summary: { type: "string", description: "A brief summary of the content." },279 is_safe: { type: "boolean", description: "Whether the content is safe for all audiences." }280 },281 required: ["summary", "is_safe"]282 }283 ]284 }285 },286 required: ["decision"]287 };288289 const moderationResultSchema = z.fromJSONSchema(moderationResultJsonSchema);290291 const client = new GoogleGenAI({});292293 const prompt = `294 Please moderate the following content and provide a decision.295 Content: 'Congratulations! You''ve won a free cruise to the Bahamas. Click here to claim your prize: www.definitely-not-a-scam.com'296 `;297298 const interaction = await client.interactions.create({299 model: "gemini-3.5-flash",300 input: prompt,301 response_format: {302 type: 'text',303 mime_type: 'application/json',304 schema: moderationResultJsonSchema305 },306 });307308 const result = moderationResultSchema.parse(JSON.parse(interaction.output_text));309 console.log(result);310311### REST312313 curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \314 -H "x-goog-api-key: $GEMINI_API_KEY" \315 -H 'Content-Type: application/json' \316 -H "Api-Revision: 2026-05-20" \317 -d '{318 "model": "gemini-3.5-flash",319 "input": "Please moderate the following content and provide a decision.\nContent: '\''Congratulations! You have won a free cruise to the Bahamas. Click here to claim your prize: www.definitely-not-a-scam.com'\''",320 "response_format": {321 "type": "text",322 "mime_type": "application/json",323 "schema": {324 "type": "object",325 "properties": {326 "decision": {327 "anyOf": [328 {329 "type": "object",330 "title": "SpamDetails",331 "description": "Details for content classified as spam.",332 "properties": {333 "reason": { "type": "string", "description": "The reason why the content is considered spam." },334 "spam_type": { "type": "string", "enum": ["phishing", "scam", "unsolicited promotion", "other"], "description": "The type of spam." }335 },336 "required": ["reason", "spam_type"]337 },338 {339 "type": "object",340 "title": "NotSpamDetails",341 "description": "Details for content classified as not spam.",342 "properties": {343 "summary": { "type": "string", "description": "A brief summary of the content." },344 "is_safe": { "type": "boolean", "description": "Whether the content is safe for all audiences." }345 },346 "required": ["summary", "is_safe"]347 }348 ]349 }350 },351 "required": ["decision"]352 }353 }354 }355 }'356357**Example Response:**358359 {360 "decision": {361 "reason": "The content is an unsolicited prize notification attempting to trick the user into clicking a suspicious link.",362 "spam_type": "scam"363 }364 }365366### Recursive Structures367368This example illustrates how to define a recursive schema such as an369organization chart.370371### Python372373 from google import genai374 from pydantic import BaseModel, Field375 from typing import List376377 class Employee(BaseModel):378 """Represents an employee in an organization."""379 name: str380 employee_id: int381 reports: List["Employee"] = Field(382 default_factory=list,383 description="A list of employees reporting to this employee."384 )385386 client = genai.Client()387388 prompt = """389 Generate an organization chart for a small team.390 The manager is Alice, who manages Bob and Charlie. Bob manages David.391 """392393 interaction = client.interactions.create(394 model="gemini-3.5-flash",395 input=prompt,396 response_format={397 "type": "text",398 "mime_type": "application/json",399 "schema": Employee.model_json_schema()400 },401 )402403 employee = Employee.model_validate_json(interaction.output_text)404 print(employee)405406### JavaScript407408 import { GoogleGenAI } from "@google/genai";409 import * as z from "zod";410411 const employeeJsonSchema = {412 type: "object",413 properties: {414 name: { type: "string" },415 employee_id: { type: "integer" },416 reports: {417 type: "array",418 description: "A list of employees reporting to this employee.",419 items: {420 "$ref": "#"421 }422 }423 },424 required: ["name", "employee_id", "reports"]425 };426427 const employeeSchema = z.fromJSONSchema(employeeJsonSchema);428429 const client = new GoogleGenAI({});430431 const prompt = `432 Generate an organization chart for a small team.433 The manager is Alice, who manages Bob and Charlie. Bob manages David.434 `;435436 const interaction = await client.interactions.create({437 model: "gemini-3.5-flash",438 input: prompt,439 response_format: {440 type: 'text',441 mime_type: 'application/json',442 schema: employeeJsonSchema443 },444 });445446 const employee = employeeSchema.parse(JSON.parse(interaction.output_text));447 console.log(employee);448449### REST450451 curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \452 -H "x-goog-api-key: $GEMINI_API_KEY" \453 -H 'Content-Type: application/json' \454 -H "Api-Revision: 2026-05-20" \455 -d '{456 "model": "gemini-3.5-flash",457 "input": "Generate an organization chart for a small team.\nThe manager is Alice, who manages Bob and Charlie. Bob manages David.",458 "response_format": {459 "type": "text",460 "mime_type": "application/json",461 "schema": {462 "type": "object",463 "properties": {464 "name": { "type": "string" },465 "employee_id": { "type": "integer" },466 "reports": {467 "type": "array",468 "description": "A list of employees reporting to this employee.",469 "items": {470 "$ref": "#"471 }472 }473 },474 "required": ["name", "employee_id", "reports"]475 }476 }477 }478 }'479480**Example Response:**481482 {483 "name": "Alice",484 "employee_id": 101,485 "reports": [486 {487 "name": "Bob",488 "employee_id": 102,489 "reports": [490 {491 "name": "David",492 "employee_id": 104,493 "reports": []494 }495 ]496 },497 {498 "name": "Charlie",499 "employee_id": 103,500 "reports": []501 }502 ]503 }504505## Streaming results506507You can stream structured outputs, allowing you to start processing the508response as it's being generated. The streamed chunks are valid partial JSON509strings that can be concatenated to form the final JSON object.510511### Python512513 from google import genai514 from pydantic import BaseModel515 from typing import Literal516517 class Feedback(BaseModel):518 sentiment: Literal["positive", "neutral", "negative"]519 summary: str520521 client = genai.Client()522 prompt = "The new UI is incredibly intuitive. Add a very long summary to test streaming!"523524 stream = client.interactions.create(525 model="gemini-3.5-flash",526 input=prompt,527 response_format={528 "type": "text",529 "mime_type": "application/json",530 "schema": Feedback.model_json_schema()531 },532 stream=True533 )534 for event in stream:535 if event.event_type == "step.delta" and event.delta.text:536 print(event.delta.text, end="")537538### JavaScript539540 import { GoogleGenAI } from "@google/genai";541 import * as z from "zod";542543 const feedbackJsonSchema = {544 type: "object",545 properties: {546 sentiment: { type: "string", enum: ["positive", "neutral", "negative"] },547 summary: { type: "string" }548 },549 required: ["sentiment", "summary"]550 };551552 const feedbackSchema = z.fromJSONSchema(feedbackJsonSchema);553554 const client = new GoogleGenAI({});555556 const stream = await client.interactions.create({557 model: "gemini-3.5-flash",558 input: "The new UI is incredibly intuitive. Add a very long summary!",559 response_format: {560 type: 'text',561 mime_type: 'application/json',562 schema: feedbackJsonSchema563 },564 stream: true,565 });566567 for await (const event of stream) {568 if (event.type === "step.delta" && event.delta?.text) {569 process.stdout.write(event.delta.text);570 }571 }572573## Structured outputs with tools574575> [!WARNING]576> **Preview:** This feature is available only to Gemini 3 series models.577578Gemini 3 lets you combine Structured Outputs with built-in tools, including579[Grounding with Google Search](https://ai.google.dev/gemini-api/docs/interactions/google-search),580[URL Context](https://ai.google.dev/gemini-api/docs/interactions/url-context),581[Code Execution](https://ai.google.dev/gemini-api/docs/interactions/code-execution),582[File Search](https://ai.google.dev/gemini-api/docs/interactions/file-search#structured-output), and583[Function Calling](https://ai.google.dev/gemini-api/docs/interactions/function-calling).584585### Python586587 from google import genai588 from pydantic import BaseModel, Field589 from typing import List590591 class MatchResult(BaseModel):592 winner: str = Field(description="The name of the winner.")593 final_match_score: str = Field(description="The final match score.")594 scorers: List[str] = Field(description="The name of the scorer.")595596 client = genai.Client()597598 interaction = client.interactions.create(599 model="gemini-3.1-pro-preview",600 input="Search for all details for the latest Euro.",601 tools=[{"type": "google_search"}, {"type": "url_context"}],602 response_format={603 "type": "text",604 "mime_type": "application/json",605 "schema": MatchResult.model_json_schema()606 },607 )608609 result = MatchResult.model_validate_json(interaction.output_text)610 print(result)611612### JavaScript613614 import { GoogleGenAI } from "@google/genai";615 import * as z from "zod";616617 const matchJsonSchema = {618 type: "object",619 properties: {620 winner: { type: "string" },621 final_match_score: { type: "string" },622 scorers: { type: "array", items: { type: "string" } }623 },624 required: ["winner", "final_match_score", "scorers"]625 };626627 const matchSchema = z.fromJSONSchema(matchJsonSchema);628629 const client = new GoogleGenAI({});630631 const interaction = await client.interactions.create({632 model: "gemini-3.1-pro-preview",633 input: "Search for all details for the latest Euro.",634 tools: [{type: "google_search"}, {type: "url_context"}],635 response_format: {636 type: 'text',637 mime_type: 'application/json',638 schema: matchJsonSchema639 },640 });641642 const match = matchSchema.parse(JSON.parse(interaction.output_text));643 console.log(match);644645### REST646647 curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \648 -H "x-goog-api-key: $GEMINI_API_KEY" \649 -H 'Content-Type: application/json' \650 -H "Api-Revision: 2026-05-20" \651 -d '{652 "model": "gemini-3.1-pro-preview",653 "input": "Search for all details for the latest Euro.",654 "tools": [{"type": "google_search"}, {"type": "url_context"}],655 "response_format": {656 "type": "text",657 "mime_type": "application/json",658 "schema": {659 "type": "object",660 "properties": {661 "winner": {"type": "string"},662 "final_match_score": {"type": "string"},663 "scorers": {"type": "array", "items": {"type": "string"}}664 },665 "required": ["winner", "final_match_score", "scorers"]666 }667 }668 }'669670## JSON schema support671672To generate a JSON object, configure `response_format` with an object (or an array containing an object) of type `text` and set its `mime_type` to `application/json`. The schema should be provided in the `schema` field.673674Gemini's structured output mode supports a subset of the675[JSON Schema](https://json-schema.org/) specification.676677The following values of `type` are supported:678679- **`string`**: For text.680- **`number`**: For floating-point numbers.681- **`integer`**: For whole numbers.682- **`boolean`**: For true or false values.683- **`object`**: For structured data with key-value pairs.684- **`array`**: For lists of items.685- **`null`** : To allow a property to be null, include `"null"` in the type array (e.g., `{"type": ["string", "null"]}`).686687These descriptive properties help guide the model:688689- **`title`**: A short description of a property.690- **`description`**: A longer and more detailed description of a property.691692### Type-specific properties693694**For `object` values:**695696- **`properties`**: An object where each key is a property name and each value is a schema for that property.697- **`required`**: An array of strings, listing which properties are mandatory.698- **`additionalProperties`** : Controls whether properties not listed in `properties` are allowed. Can be a boolean or a schema.699700**For `string` values:**701702- **`enum`**: Lists a specific set of possible strings for classification tasks.703- **`format`** : Specifies a syntax for the string, such as `date-time`, `date`, `time`.704705**For `number` and `integer` values:**706707- **`enum`**: Lists a specific set of possible numeric values.708- **`minimum`**: The minimum inclusive value.709- **`maximum`**: The maximum inclusive value.710711**For `array` values:**712713- **`items`**: Defines the schema for all items in the array.714- **`prefixItems`**: Defines a list of schemas for the first N items, allowing for tuple-like structures.715- **`minItems`**: The minimum number of items in the array.716- **`maxItems`**: The maximum number of items in the array.717718## Structured outputs versus function calling719720| Feature | Primary Use Case |721|---|---|722| **Structured Outputs** | **Formatting the final response.** Use when you want the model's *answer* in a specific format. |723| **Function Calling** | **Taking action during conversation.** Use when the model needs to *ask you* to perform a task before providing a final answer. |724725## Best practices726727- **Clear descriptions:** Use the `description` field to guide the model.728- **Strong typing:** Use specific types (`integer`, `string`, `enum`).729- **Prompt engineering:** Clearly state what you want the model to do.730- **Validation:** While output is syntactically correct JSON, always validate values in your application.731- **Error handling:** Implement robust error handling for schema-compliant but semantically incorrect outputs.732733## Limitations734735- **Schema subset:** Not all JSON Schema features are supported.736- **Schema complexity:** Very large or deeply nested schemas may be rejected.