> ## AI Agent Context
> Get the complete documentation index at: https://aistudio.google.com/llms.txt
> Use this file to discover all available pages.
> For the full documentation in a single file, fetch: https://aistudio.google.com/llms-full.txt

# Structured outputs

You can configure Gemini models to generate responses that adhere to a provided
JSON Schema. This ensures predictable, type-safe results and simplifies
extracting structured data from unstructured text.

Using structured outputs is ideal for:

* **Data extraction:** Pull specific information like names and dates from text.
* **Structured classification:** Classify text into predefined categories.
* **Agentic workflows:** Generate structured inputs for tools or APIs.

In addition to supporting JSON Schema in the REST API, the Google GenAI SDKs
make it easy to define schemas using
[Pydantic](https://docs.pydantic.dev/latest/) (Python) and
[Zod](https://zod.dev/) (JavaScript).

## Structured output examples  {% id="structured-output-examples" %}

### Recipe Extractor  {% id="recipe" %}

This example demonstrates how to extract structured data from text using basic
JSON Schema types like `object`, `array`, `string`, and `integer`.

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from pydantic import BaseModel, Field
    from typing import List, Optional
  
    class Ingredient(BaseModel):
        name: str = Field(description="Name of the ingredient.")
        quantity: str = Field(description="Quantity of the ingredient, including units.")
  
    class Recipe(BaseModel):
        recipe_name: str = Field(description="The name of the recipe.")
        prep_time_minutes: Optional[int] = Field(description="Optional time in minutes to prepare the recipe.")
        ingredients: List[Ingredient]
        instructions: List[str]
  
    client = genai.Client()
  
    prompt = """
    Please extract the recipe from the following text.
    The user wants to make delicious chocolate chip cookies.
    They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,
    1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,
    3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.
    For the best part, they'll need 2 cups of semisweet chocolate chips.
    First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,
    baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar
    until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry
    ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons
    onto ungreased baking sheets and bake for 9 to 11 minutes.
    """
  
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents=prompt,
        config={
            "response_mime_type": "application/json",
            "response_json_schema": Recipe.model_json_schema(),
        },
    )
  
    recipe = Recipe.model_validate_json(response.text)
    print(recipe)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from "@google/genai";
    import { z } from "zod";
  
    const ingredientSchema = z.object({
      name: z.string().describe("Name of the ingredient."),
      quantity: z.string().describe("Quantity of the ingredient, including units."),
    });
  
    const recipeSchema = z.object({
      recipe_name: z.string().describe("The name of the recipe."),
      prep_time_minutes: z.number().optional().describe("Optional time in minutes to prepare the recipe."),
      ingredients: z.array(ingredientSchema),
      instructions: z.array(z.string()),
    });
  
    const ai = new GoogleGenAI({});
  
    const prompt = `
    Please extract the recipe from the following text.
    The user wants to make delicious chocolate chip cookies.
    They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,
    1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,
    3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.
    For the best part, they'll need 2 cups of semisweet chocolate chips.
    First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,
    baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar
    until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry
    ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons
    onto ungreased baking sheets and bake for 9 to 11 minutes.
    `;
  
    const response = await ai.models.generateContent({
      model: "gemini-4-hydrogen",
      contents: prompt,
      config: {
        responseMimeType: "application/json",
        responseJsonSchema: z.toJSONSchema(recipeSchema),
      },
    });
  
    const recipe = recipeSchema.parse(JSON.parse(response.text));
    console.log(recipe);
  ```

  {% /tab %}

  {% tab label="Go" %}
  ```go
    package main
  
    import (
        "context"
        "fmt"
        "log"
  
        "google.golang.org/genai"
    )
  
    func main() {
        ctx := context.Background()
        client, err := genai.NewClient(ctx, nil)
        if err != nil {
            log.Fatal(err)
        }
  
        prompt := `
      Please extract the recipe from the following text.
      The user wants to make delicious chocolate chip cookies.
      They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,
      1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,
      3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.
      For the best part, they'll need 2 cups of semisweet chocolate chips.
      First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,
      baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar
      until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry
      ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons
      onto ungreased baking sheets and bake for 9 to 11 minutes.
      `
        config := &genai.GenerateContentConfig{
            ResponseMIMEType: "application/json",
            ResponseJsonSchema: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "recipe_name": map[string]any{
                        "type": "string",
                        "description": "The name of the recipe.",
                    },
                    "prep_time_minutes": map[string]any{
                        "type": "integer",
                        "description": "Optional time in minutes to prepare the recipe.",
                    },
                    "ingredients": map[string]any{
                        "type": "array",
                        "items": map[string]any{
                            "type": "object",
                            "properties": map[string]any{
                                "name": map[string]any{
                                    "type": "string",
                                    "description": "Name of the ingredient.",
                                },
                                "quantity": map[string]any{
                                    "type": "string",
                                    "description": "Quantity of the ingredient, including units.",
                                },
                            },
                            "required": []string{"name", "quantity"},
                        },
                    },
                    "instructions": map[string]any{
                        "type": "array",
                        "items": map[string]any{"type": "string"},
                    },
                },
                "required": []string{"recipe_name", "ingredients", "instructions"},
            },
        }
  
        result, err := client.Models.GenerateContent(
            ctx,
            "gemini-4-hydrogen",
            genai.Text(prompt),
            config,
        )
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(result.Text())
    }
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-hydrogen:generateContent" \
        -H "x-goog-api-key: $GEMINI_API_KEY" \
        -H 'Content-Type: application/json' \
        -X POST \
        -d '{
          "contents": [{
            "parts":[
              { "text": "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." }
            ]
          }],
          "generationConfig": {
            "responseFormat": {
              "text": {
                "mimeType": "APPLICATION_JSON",
                "schema": {
                  "type": "object",
                  "properties": {
                    "recipe_name": {
                      "type": "string",
                      "description": "The name of the recipe."
                    },
                    "prep_time_minutes": {
                      "type": "integer",
                      "description": "Optional time in minutes to prepare the recipe."
                    },
                    "ingredients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": { "type": "string", "description": "Name of the ingredient."},
                          "quantity": { "type": "string", "description": "Quantity of the ingredient, including units."}
                        },
                        "required": ["name", "quantity"]
                      }
                    },
                    "instructions": {
                      "type": "array",
                      "items": { "type": "string" }
                    }
                  },
                  "required": ["recipe_name", "ingredients", "instructions"]
                }
              }
            }
          }
        }'
  ```

  {% /tab %}

{% /tabs %}

**Example Response:**

```json
{
  "recipe_name": "Delicious Chocolate Chip Cookies",
  "ingredients": [
    {
      "name": "all-purpose flour",
      "quantity": "2 and 1/4 cups"
    },
    {
      "name": "baking soda",
      "quantity": "1 teaspoon"
    },
    {
      "name": "salt",
      "quantity": "1 teaspoon"
    },
    {
      "name": "unsalted butter (softened)",
      "quantity": "1 cup"
    },
    {
      "name": "granulated sugar",
      "quantity": "3/4 cup"
    },
    {
      "name": "packed brown sugar",
      "quantity": "3/4 cup"
    },
    {
      "name": "vanilla extract",
      "quantity": "1 teaspoon"
    },
    {
      "name": "large eggs",
      "quantity": "2"
    },
    {
      "name": "semisweet chocolate chips",
      "quantity": "2 cups"
    }
  ],
  "instructions": [
    "Preheat the oven to 375°F (190°C).",
    "In a small bowl, whisk together the flour, baking soda, and salt.",
    "In a large bowl, cream together the butter, granulated sugar, and brown sugar until light and fluffy.",
    "Beat in the vanilla and eggs, one at a time.",
    "Gradually beat in the dry ingredients until just combined.",
    "Stir in the chocolate chips.",
    "Drop by rounded tablespoons onto ungreased baking sheets and bake for 9 to 11 minutes."
  ]
}
```

### Content Moderation  {% id="feedback" %}

This example showcases `anyOf` for conditional schemas and `enum` for
classification, allowing the output structure to vary based on the content.

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from pydantic import BaseModel, Field
    from typing import Union, Literal
  
    class SpamDetails(BaseModel):
        reason: str = Field(description="The reason why the content is considered spam.")
        spam_type: Literal["phishing", "scam", "unsolicited promotion", "other"] = Field(description="The type of spam.")
  
    class NotSpamDetails(BaseModel):
        summary: str = Field(description="A brief summary of the content.")
        is_safe: bool = Field(description="Whether the content is safe for all audiences.")
  
    class ModerationResult(BaseModel):
        decision: Union[SpamDetails, NotSpamDetails]
  
    client = genai.Client()
  
    prompt = """
    Please moderate the following content and provide a decision.
    Content: 'Congratulations! You''ve won a free cruise to the Bahamas. Click here to claim your prize: www.definitely-not-a-scam.com'
    """
  
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents=prompt,
        config={
            "response_mime_type": "application/json",
            "response_json_schema": ModerationResult.model_json_schema(),
        },
    )
  
    result = ModerationResult.model_validate_json(response.text)
    print(result)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from "@google/genai";
    import { z } from "zod";
  
    const spamDetailsSchema = z.object({
      reason: z.string().describe("The reason why the content is considered spam."),
      spam_type: z.enum(["phishing", "scam", "unsolicited promotion", "other"]).describe("The type of spam."),
    });
  
    const notSpamDetailsSchema = z.object({
      summary: z.string().describe("A brief summary of the content."),
      is_safe: z.boolean().describe("Whether the content is safe for all audiences."),
    });
  
    const moderationResultSchema = z.object({
      decision: z.union([spamDetailsSchema, notSpamDetailsSchema]),
    });
  
    const ai = new GoogleGenAI({});
  
    const prompt = `
    Please moderate the following content and provide a decision.
    Content: 'Congratulations! You''ve won a free cruise to the Bahamas. Click here to claim your prize: www.definitely-not-a-scam.com'
    `;
  
    const response = await ai.models.generateContent({
      model: "gemini-4-hydrogen",
      contents: prompt,
      config: {
        responseMimeType: "application/json",
        responseJsonSchema: z.toJSONSchema(moderationResultSchema),
      },
    });
  
    const result = moderationResultSchema.parse(JSON.parse(response.text));
    console.log(result);
  ```

  {% /tab %}

  {% tab label="Go" %}
  ```go
    package main
  
    import (
        "context"
        "fmt"
        "log"
  
        "google.golang.org/genai"
    )
  
    func main() {
        ctx := context.Background()
        client, err := genai.NewClient(ctx, nil)
        if err != nil {
            log.Fatal(err)
        }
  
        prompt := `
      Please moderate the following content and provide a decision.
      Content: 'Congratulations! You''ve won a free cruise to the Bahamas. Click here to claim your prize: www.definitely-not-a-scam.com'
      `
        config := &genai.GenerateContentConfig{
            ResponseMIMEType: "application/json",
            ResponseJsonSchema: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "decision": map[string]any{
                        "anyOf": []map[string]any{
                            {
                                "type": "object",
                                "title": "SpamDetails",
                                "description": "Details for content classified as spam.",
                                "properties": map[string]any{
                                    "reason": map[string]any{
                                        "type": "string",
                                        "description": "The reason why the content is considered spam.",
                                    },
                                    "spam_type": map[string]any{
                                        "type": "string",
                                        "enum": []string{"phishing", "scam", "unsolicited promotion", "other"},
                                        "description": "The type of spam.",
                                    },
                                },
                                "required": []string{"reason", "spam_type"},
                            },
                            {
                                "type": "object",
                                "title": "NotSpamDetails",
                                "description": "Details for content classified as not spam.",
                                "properties": map[string]any{
                                    "summary": map[string]any{
                                        "type": "string",
                                        "description": "A brief summary of the content.",
                                    },
                                    "is_safe": map[string]any{
                                        "type": "boolean",
                                        "description": "Whether the content is safe for all audiences.",
                                    },
                                },
                                "required": []string{"summary", "is_safe"},
                            },
                        },
                    },
                },
                "required": []string{"decision"},
            },
        }
  
        result, err := client.Models.GenerateContent(
            ctx,
            "gemini-4-hydrogen",
            genai.Text(prompt),
            config,
        )
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(result.Text())
    }
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-hydrogen:generateContent" \
        -H "x-goog-api-key: $GEMINI_API_KEY" \
        -H 'Content-Type: application/json' \
        -X POST \
        -d '{
          "contents": [{
            "parts":[
              { "text": "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''" }
            ]
          }],
          "generationConfig": {
            "responseFormat": {
              "text": {
                "mimeType": "APPLICATION_JSON",
                "schema": {
                  "type": "object",
                  "properties": {
                    "decision": {
                      "anyOf": [
                        {
                          "type": "object",
                          "title": "SpamDetails",
                          "description": "Details for content classified as spam.",
                          "properties": {
                            "reason": { "type": "string", "description": "The reason why the content is considered spam." },
                            "spam_type": { "type": "string", "enum": ["phishing", "scam", "unsolicited promotion", "other"], "description": "The type of spam." }
                          },
                          "required": ["reason", "spam_type"]
                        },
                        {
                          "type": "object",
                          "title": "NotSpamDetails",
                          "description": "Details for content classified as not spam.",
                          "properties": {
                            "summary": { "type": "string", "description": "A brief summary of the content." },
                            "is_safe": { "type": "boolean", "description": "Whether the content is safe for all audiences." }
                          },
                          "required": ["summary", "is_safe"]
                        }
                      ]
                    }
                  },
                  "required": ["decision"]
                }
              }
            }
          }
         }'
  ```

  {% /tab %}

{% /tabs %}

**Example Response:**

```json
{
  "decision": {
    "reason": "The content is an unsolicited prize notification attempting to trick the user into clicking a suspicious link.",
    "spam_type": "scam"
  }
}
```

### Recursive Structures  {% id="recursive" %}

This example illustrates how to define a recursive schema such as an
organization chart.

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from pydantic import BaseModel, Field
    from typing import List
  
    class Employee(BaseModel):
        """Represents an employee in an organization."""
        name: str
        employee_id: int
        reports: List["Employee"] = Field(
            default_factory=list,
            description="A list of employees reporting to this employee."
        )
  
    client = genai.Client()
  
    prompt = """
    Generate an organization chart for a small team.
    The manager is Alice, who manages Bob and Charlie. Bob manages David.
    """
  
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents=prompt,
        config={
            "response_mime_type": "application/json",
            "response_json_schema": Employee.model_json_schema(),
        },
    )
  
    employee = Employee.model_validate_json(response.text)
    print(employee)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from "@google/genai";
    import { z } from "zod";
  
    const employeeSchema = z.object({
      name: z.string(),
      employee_id: z.number().int(),
      reports: z.lazy(() => z.array(employeeSchema)).describe("A list of employees reporting to this employee."),
    });
  
    const ai = new GoogleGenAI({});
  
    const prompt = `
    Generate an organization chart for a small team.
    The manager is Alice, who manages Bob and Charlie. Bob manages David.
    `;
  
    const response = await ai.models.generateContent({
      model: "gemini-4-hydrogen",
      contents: prompt,
      config: {
        responseMimeType: "application/json",
        responseJsonSchema: z.toJSONSchema(employeeSchema),
      },
    });
  
    const employee = employeeSchema.parse(JSON.parse(response.text));
    console.log(employee);
  ```

  {% /tab %}

  {% tab label="Go" %}
  ```go
    package main
  
    import (
        "context"
        "fmt"
        "log"
  
        "google.golang.org/genai"
    )
  
    func main() {
        ctx := context.Background()
        client, err := genai.NewClient(ctx, nil)
        if err != nil {
            log.Fatal(err)
        }
  
        prompt := `
      Generate an organization chart for a small team.
      The manager is Alice, who manages Bob and Charlie. Bob manages David.
      `
        config := &genai.GenerateContentConfig{
            ResponseMIMEType: "application/json",
            ResponseJsonSchema: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "name":        map[string]any{"type": "string"},
                    "employee_id": map[string]any{"type": "integer"},
                    "reports": map[string]any{
                        "type":        "array",
                        "description": "A list of employees reporting to this employee.",
                        "items": map[string]any{
                            "$ref": "#",
                        },
                    },
                },
                "required": []string{"name", "employee_id", "reports"},
            },
        }
  
        result, err := client.Models.GenerateContent(
            ctx,
            "gemini-4-hydrogen",
            genai.Text(prompt),
            config,
        )
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(result.Text())
    }
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-hydrogen:generateContent" \
        -H "x-goog-api-key: $GEMINI_API_KEY" \
        -H 'Content-Type: application/json' \
        -X POST \
        -d '{
          "contents": [{
            "parts":[
              { "text": "Generate an organization chart for a small team.\nThe manager is Alice, who manages Bob and Charlie. Bob manages David." }
            ]
          }],
          "generationConfig": {
            "responseFormat": {
              "text": {
                "mimeType": "APPLICATION_JSON",
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": { "type": "string" },
                    "employee_id": { "type": "integer" },
                    "reports": {
                      "type": "array",
                      "description": "A list of employees reporting to this employee.",
                      "items": {
                        "$ref": "#"
                      }
                    }
                  },
                  "required": ["name", "employee_id", "reports"]
                }
              }
            }
          }
        }'
  ```

  {% /tab %}

{% /tabs %}

**Example Response:**

```json
{
  "name": "Alice",
  "employee_id": 101,
  "reports": [
    {
      "name": "Bob",
      "employee_id": 102,
      "reports": [
        {
          "name": "David",
          "employee_id": 104,
          "reports": []
        }
      ]
    },
    {
      "name": "Charlie",
      "employee_id": 103,
      "reports": []
    }
  ]
}
```

## Streaming  {% id="streaming" %}

You can stream structured outputs, which allows you to start processing the
response as it's being generated, without having to wait for the entire output
to be complete. This can improve the perceived performance of your application.

The streamed chunks will be valid partial JSON strings, which can be
concatenated to form the final, complete JSON object.

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from pydantic import BaseModel, Field
    from typing import Literal
  
    class Feedback(BaseModel):
        sentiment: Literal["positive", "neutral", "negative"]
        summary: str
  
    client = genai.Client()
    prompt = "The new UI is incredibly intuitive and visually appealing. Great job. Add a very long summary to test streaming!"
  
    response_stream = client.models.generate_content_stream(
        model="gemini-4-hydrogen",
        contents=prompt,
        config={
            "response_mime_type": "application/json",
            "response_json_schema": Feedback.model_json_schema(),
        },
    )
  
    for chunk in response_stream:
        print(chunk.candidates[0].content.parts[0].text)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from "@google/genai";
    import { z } from "zod";
  
    const ai = new GoogleGenAI({});
    const prompt = "The new UI is incredibly intuitive and visually appealing. Great job! Add a very long summary to test streaming!";
  
    const feedbackSchema = z.object({
      sentiment: z.enum(["positive", "neutral", "negative"]),
      summary: z.string(),
    });
  
    const stream = await ai.models.generateContentStream({
      model: "gemini-4-hydrogen",
      contents: prompt,
      config: {
        responseMimeType: "application/json",
        responseJsonSchema: z.toJSONSchema(feedbackSchema),
      },
    });
  
    for await (const chunk of stream) {
      console.log(chunk.candidates[0].content.parts[0].text)
    }
  ```

  {% /tab %}

{% /tabs %}

## Structured outputs with tools  {% id="structured-outputs-with-tools" %}

{% callout type="note" %}
  Preview: This feature is available only to Gemini 4 and Gemini 3 series models,
  such as `gemini-4-carbon`, `gemini-4-argon`, `gemini-4-hydrogen`, and `gemini-3.8-flash`.

{% /callout %}

Gemini 4 and Gemini 3 let you combine Structured Outputs with built-in tools, including
[Grounding with Google Search](/docs/google-search),
[URL Context](/docs/url-context),
[Code Execution](/docs/code-execution),
[File Search](/docs/file-search#structured-output), and
[Function Calling](/docs/function-calling).

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from pydantic import BaseModel, Field
    from typing import List
  
    class MatchResult(BaseModel):
        winner: str = Field(description="The name of the winner.")
        final_match_score: str = Field(description="The final match score.")
        scorers: List[str] = Field(description="The name of the scorer.")
  
    client = genai.Client()
  
    response = client.models.generate_content(
        model="gemini-4-carbon",
        contents="Search for all details for the latest Euro.",
        config={
            "tools": [
                {"google_search": {}},
                {"url_context": {}}
            ],
            "response_mime_type": "application/json",
            "response_json_schema": MatchResult.model_json_schema(),
        },
    )
  
    result = MatchResult.model_validate_json(response.text)
    print(result)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from "@google/genai";
    import { z } from "zod";
  
    const ai = new GoogleGenAI({});
  
    const matchSchema = z.object({
      winner: z.string().describe("The name of the winner."),
      final_match_score: z.string().describe("The final score."),
      scorers: z.array(z.string()).describe("The name of the scorer.")
    });
  
    async function run() {
      const response = await ai.models.generateContent({
        model: "gemini-4-carbon",
        contents: "Search for all details for the latest Euro.",
        config: {
          tools: [
            { googleSearch: {} },
            { urlContext: {} }
          ],
          responseMimeType: "application/json",
          responseJsonSchema: z.toJSONSchema(matchSchema),
        },
      });
  
      const match = matchSchema.parse(JSON.parse(response.text));
      console.log(match);
    }
  
    run();
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```bash
    curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-carbon:generateContent" \
      -H "x-goog-api-key: $GEMINI_API_KEY" \
      -H 'Content-Type: application/json' \
      -X POST \
      -d '{
        "contents": [{
          "parts": [{"text": "Search for all details for the latest Euro."}]
        }],
        "tools": [
          {"googleSearch": {}},
          {"urlContext": {}}
        ],
        "generationConfig": {
          "responseFormat": {
            "text": {
              "mimeType": "APPLICATION_JSON",
              "schema": {
                "type": "object",
                "properties": {
                  "winner": {"type": "string", "description": "The name of the winner."},
                  "final_match_score": {"type": "string", "description": "The final score."},
                  "scorers": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "The name of the scorer."
                  }
                },
                "required": ["winner", "final_match_score", "scorers"]
              }
            }
          }
        }
      }'
  ```

  {% /tab %}

{% /tabs %}

## JSON schema support  {% id="json-schema-support" %}

To generate a JSON object, set `response_json_schema` (or `responseFormat.text.schema` in REST) in the generation configuration. The schema must be a valid [JSON Schema](https://json-schema.org/) that describes the desired output format.

The model will then generate a response that is a syntactically valid JSON
string matching the provided schema. When using structured outputs, the model
will produce outputs in the same order as the keys in the schema.

Gemini's structured output mode supports a subset of the
[JSON Schema](https://json-schema.org) specification.

The following values of `type` are supported:

* **`string`**: For text.
* **`number`**: For floating-point numbers.
* **`integer`**: For whole numbers.
* **`boolean`**: For true/false values.
* **`object`**: For structured data with key-value pairs.
* **`array`**: For lists of items.
* **`null`**: To allow a property to be null, include `"null"` in the type array (e.g., `{"type": ["string", "null"]}`).

These descriptive properties help guide the model:

* **`title`**: A short description of a property.
* **`description`**: A longer and more detailed description of a property.

### Type-specific properties  {% id="type-specific-properties" %}

**For `object` values:**

* **`properties`**: An object where each key is a property name and each value is a schema for that property.
* **`required`**: An array of strings, listing which properties are mandatory.
* **`additionalProperties`**: Controls whether properties not listed in `properties` are allowed. Can be a boolean or a schema.

**For `string` values:**

* **`enum`**: Lists a specific set of possible strings for classification tasks.
* **`format`**: Specifies a syntax for the string, such as `date-time`, `date`, `time`.

**For `number` and `integer` values:**

* **`enum`**: Lists a specific set of possible numeric values.
* **`minimum`**: The minimum inclusive value.
* **`maximum`**: The maximum inclusive value.

**For `array` values:**

* **`items`**: Defines the schema for all items in the array.
* **`prefixItems`**: Defines a list of schemas for the first N items, allowing for tuple-like structures.
* **`minItems`**: The minimum number of items in the array.
* **`maxItems`**: The maximum number of items in the array.

## Model support  {% id="model-support" %}

The following models support structured output:

| Model | Structured Outputs |
| --- | :---: |
| Gemini 4 Carbon | ✔️ |
| Gemini 4 Argon | ✔️ |
| Gemini 4 Hydrogen | ✔️ |
| Gemini 3.8 Flash | ✔️ |
| Gemini 3.6 Flash | ✔️ |
| Gemini 3.5 Flash-Lite | ✔️ |
| Gemini 3.1 Flash-Lite | ✔️ |
| Gemini 3.1 Pro Preview | ✔️ |
| Gemini 3.1 Flash-Lite Preview | ✔️ |
| Gemini 2.5 Pro | ✔️ |
| Gemini 2.5 Flash | ✔️ |
| Gemini 2.5 Flash-Lite | ✔️ |
| Gemini 2.0 Flash | ✔️* |
| Gemini 2.0 Flash-Lite | ✔️* |

*\* Note that Gemini 2.0 requires an explicit `propertyOrdering` list within the JSON input to define the preferred structure. You can find an example in this [cookbook](https://github.com/google-gemini/cookbook/blob/main/examples/Pdf_structured_outputs_on_invoices_and_forms.ipynb).*

## Structured outputs vs. function calling  {% id="structured-outputs-vs-function-calling" %}

Both structured outputs and function calling use JSON schemas, but they serve
different purposes:

| Feature | Primary Use Case |
| :--- | :--- |
| **Structured Outputs** | **Formatting the final response to the user.** Use this when you want the model's *answer* to be in a specific format (e.g., extracting data from a document to save to a database). |
| **Function Calling** | **Taking action during the conversation.** Use this when the model needs to *ask you* to perform a task (e.g., "get current weather") before it can provide a final answer. |

## Best practices  {% id="best-practices" %}

* **Clear descriptions:** Use the `description` field in your schema to provide
  clear instructions to the model about what each property represents. This is
  crucial for guiding the model's output.
* **Strong typing:** Use specific types (`integer`, `string`, `enum`) whenever
  possible. If a parameter has a limited set of valid values, use an `enum`.
* **Prompt engineering:** Clearly state in your prompt what you want the model
  to do. For example, "Extract the following information from the text..." or
  "Classify this feedback according to the provided schema...".
* **Validation:** While structured output guarantees syntactically correct JSON,
  it does not guarantee the values are semantically correct. Always validate the
  final output in your application code before using it.
* **Error handling:** Implement robust error handling in your application to
  gracefully manage cases where the model's output, while schema-compliant, may
  not meet your business logic requirements.

## Limitations  {% id="limitations" %}

* **Schema subset:** Not all features of the JSON Schema specification are
  supported. The model ignores unsupported properties.
* **Schema complexity:** Very large or deeply nested schemas may be rejected.

### Simplifying complex schemas  {% id="simplifying-complex-schemas" %}

When you request structured output, the API compiles your JSON Schema into a
state machine that constrains token generation. This state machine enforces
limits on total states, branching paths, and nesting depth. If your schema
exceeds these limits, the API rejects the request with a
`400 INVALID_ARGUMENT` error.

To fix schema rejection errors, reduce the structural depth and branching
factor of your schema. You can simplify complex schemas in several ways:

* **Move non-structural rules to descriptions:** Field `description` properties
  and system instructions guide the model without adding states to the output
  grammar. If complex constraints push your schema over the limit, move those
  rules into concise descriptions and validate the response in your application
  code.
* **Flatten nested objects and bound recursion:** Replace deeply nested object
  hierarchies with flatter structures. If you use `$defs` and `$ref` for
  recursive types, make the recursive reference optional or nullable. Avoid
  recursing through required properties or arrays with `minItems` greater than
  zero.
* **Reduce branching from optional fields, enums, and unions:** Optional
  properties, `enum` values, and `anyOf` branches multiply the branching paths
  in the output grammar. Mark properties as `required` where possible and allow
  `null` values when a field can be empty. Trim large `enum` lists and simplify
  `anyOf` unions, or include the constraint in your prompt (for example, with a
  Pydantic schema) as a softer restriction.
* **Shorten property names and drop array or numeric bounds:** Property keys
  consume states proportional to their character length. Array bounds such as
  `minItems` and `maxItems` duplicate the item schema for each counted
  position, and numeric bounds (`minimum` and `maximum`) also increase the
  state space. Use concise property names, remove unused fields, and either
  include bounds in your prompt (for example, with a Pydantic schema) as a
  softer restriction or validate bounds in your application code.

