# Structured output

> Constrain model output with response_format, and how to recover when parsing fails.

When you need machine-readable output, constrain the format with `response_format` instead of writing
"output only JSON" in the prompt.

## JSON object mode

```python
resp = client.chat.completions.create(
    model="gpt-5.4-mini",
    messages=[{"role": "user", "content": "Extract 'Jane, 28, Berlin' as JSON"}],
    response_format={"type": "json_object"},
)
print(resp.choices[0].message.content)   # {"name":"Jane","age":28,"city":"Berlin"}
```

<Callout type="warn" title="json_object wants the word JSON in the prompt">
The OpenAI protocol requires the prompt to mention "JSON" in `json_object` mode; otherwise some models
error out. JSON Schema mode is the sturdier option.
</Callout>

## JSON Schema mode

```python
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"},
        "city": {"type": "string"},
    },
    "required": ["name", "age", "city"],
    "additionalProperties": False,
}

resp = client.chat.completions.create(
    model="gpt-5.4-mini",
    messages=[{"role": "user", "content": "Extract 'Jane, 28, Berlin' as structured data"}],
    response_format={"type": "json_schema", "json_schema": {"name": "person", "schema": schema, "strict": True}},
)
```

## When parsing fails

Keep a fallback even with a schema:

1. Try `json.loads`; on failure, send the **raw text** plus the error back and ask the model to fix the
   format only
2. If that fails again, degrade to "return raw text and ask a human"
3. Never silently drop an unparseable response — users read it as "the model said nothing"

## Support varies by model

- Models with strict `json_schema` honour types and required fields most reliably
- Models with only `json_object` may still deviate in field names or types
- Models with no `response_format` support can only be constrained by prompt, so the fallback above
  matters

See [Models](/en/models/).
