Skip to main content

Overview

Structured outputs enforce JSON Schema validation on model responses, ensuring consistent, type-safe outputs. This eliminates parsing errors and hallucinated fields, simplifying downstream integrations.

Request Format

Use response_format with type: "json_schema":
{
  "model": "openai/gpt-5-mini",
  "messages": [
    {"role": "user", "content": "What's the weather like in London?"}
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "weather",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "City or location name"
          },
          "temperature": {
            "type": "number",
            "description": "Temperature in Celsius"
          },
          "conditions": {
            "type": "string",
            "description": "Weather conditions description"
          }
        },
        "required": ["location", "temperature", "conditions"],
        "additionalProperties": false
      }
    }
  }
}

Response Format

The model returns JSON matching your schema:
{
  "choices": [{
    "message": {
      "content": "{\"location\": \"London\", \"temperature\": 18, \"conditions\": \"Partly cloudy with light drizzle\"}"
    }
  }]
}
Parse the content as JSON:
import json

response = client.chat.completions.create(...)
content = response.choices[0].message.content
weather_data = json.loads(content)

Schema Configuration

name

Schema identifier (required):
{
  "name": "weather_response"
}

strict

Enforce strict validation (default: false):
  • true: Reject responses that don’t match schema exactly
  • false: Allow minor deviations

schema

JSON Schema object defining the structure:
{
  "type": "object",
  "properties": {
    "field": {"type": "string"}
  },
  "required": ["field"],
  "additionalProperties": false
}

JSON Schema Support

Supported JSON Schema features:
  • Basic types: string, number, integer, boolean, array, object
  • Constraints: enum, minLength, maxLength, minimum, maximum
  • Nested objects and arrays
  • required fields
  • additionalProperties control

Model Support

View Structured Output Models

For a complete list of models supporting structured outputs, visit anannas.ai/models and filter by json_mode capability.
Structured outputs are supported on:
  • OpenAI: GPT-4, GPT-4 Turbo, GPT-5 Mini, GPT-5, o1, o3
  • Anthropic: Claude 3 Opus, Claude 3 Sonnet, Claude Sonnet 4.5
  • Other providers: Check /v1/models for json_mode capability
Query available models:
curl https://api.anannas.ai/v1/models \
  -H "Authorization: Bearer $ANANNAS_API_KEY" | \
  jq '.data[] | select(.capabilities[] | contains("json_mode"))'

Best Practices

  1. Property descriptions: Guide the model with clear descriptions
  2. Use strict mode: Set strict: true for production
  3. Keep schemas simple: Simpler schemas yield more reliable results
  4. Required fields: Explicitly mark required fields
  5. Type constraints: Use enum for limited options

Example: Type-Safe Response

from openai import OpenAI
import json

client = OpenAI(
    base_url="https://api.anannas.ai/v1",
    api_key="<ANANNAS_API_KEY>"
)

response = client.chat.completions.create(
    model="openai/gpt-5-mini",
    messages=[
        {"role": "user", "content": "Extract user info from: John Doe, age 30, email [email protected]"}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "user_info",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "email": {"type": "string"}
                },
                "required": ["name", "age", "email"],
                "additionalProperties": False
            }
        }
    }
)

content = response.choices[0].message.content
user_data = json.loads(content)
# Type-safe: user_data["name"], user_data["age"], user_data["email"]

Streaming with Structured Outputs

Structured outputs work with streaming:
{
  "stream": true,
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "weather",
      "strict": true,
      "schema": {...}
    }
  }
}
Accumulate content deltas and parse the complete JSON when the stream completes.

Error Handling

Common errors:
  1. Unsupported model: Error with unsupported_parameter type
  2. Invalid schema: Request rejected before completion
  3. Schema violation: Response fails validation in strict mode
try:
    response = client.chat.completions.create(...)
    content = json.loads(response.choices[0].message.content)
except json.JSONDecodeError:
    print("Failed to parse structured output")
except Exception as e:
    if "unsupported_parameter" in str(e):
        print("Model does not support structured outputs")

Comparison: JSON Object vs JSON Schema

JSON Object Mode

Simple JSON output without validation:
{
  "response_format": {
    "type": "json_object"
  }
}

JSON Schema Mode

Strict validation with schema:
{
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "response",
      "strict": true,
      "schema": {...}
    }
  }
}

See Also