SPB Git

Repository Public

structured-output.md 26.4 KB 736 lines markdown

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.
Files main
Menu

Theme