Last updated: October 2026
- All three providers now enforce a JSON schema: Claude through
output_config.format, OpenAI throughjson_schemawithstrict: true, Gemini through aresponse_formatschema. - Claude rejects length constraints: minLength, maxLength, minimum and maximum are unsupported, so a 60-character title limit needs a code check.
- Gemini supports minimum, maximum, minItems and maxItems, which makes it the only one of the three that can bound numeric scores and list sizes in the schema itself.
- A valid schema does not mean a valid answer: a refusal or a max_tokens cut-off can return HTTP 200 with output that does not match.
An SEO pipeline that writes title tags, meta descriptions, FAQ schema and internal link suggestions needs JSON it can feed straight into WordPress or Rank Math.
Free-form prompts that say “respond only in JSON” fail on roughly the schedule you would expect from a language model: rarely, and always on the batch you were not watching.
How Do You Switch On Structured Outputs on Each Provider?
On Claude you set output_config.format.type to json_schema and pass the schema. The Python SDK wraps this as client.messages.parse(output_format=YourModel), per Anthropic’s structured outputs documentation. It lists Claude Sonnet 5.5, Opus 5.5 and Haiku 4.5 among supported models.
On OpenAI you pass a json_schema response format with strict: true. OpenAI’s structured outputs guide lists gpt-4o-mini and gpt-4o-2024-08-06 and later as supported.
On Gemini you set a response_format with mime_type of application/json and a schema, per Google’s Gemini structured output documentation. The page names Gemini 3.8 Flash and Gemini 3.1 Pro Preview.
Define the schema once as a Pydantic or Zod model and generate the provider-specific JSON from it. Hand-written schemas drift apart across three providers within a week.

Which Schema Keywords Survive on Each Provider?
This is where pipelines break. A schema that validates in your editor can be rejected by the API, or silently stripped of the constraint you cared about.
| Keyword | Claude | Gemini |
|---|---|---|
| minLength / maxLength | Not supported | Not listed |
| minimum / maximum | Not supported | Supported |
| minItems / maxItems | minItems of 0 or 1 only | Both supported |
| additionalProperties | Must be false | Supported |
| Recursive schemas | Not supported | Not stated; deep nesting may be rejected |
| enum | Strings, numbers, bools, nulls | Strings and numbers |
OpenAI requires every field to be declared as required and additionalProperties set to false, per its guide. The table omits OpenAI because the page does not spell out the full keyword list, and a half-filled column would mislead.

Why Can a Claude Schema Not Cap a Meta Description at 155 Characters?
Because maxLength is on the unsupported list. The model is told the shape, not the length, so a description field can come back at 170 characters and still be “valid”.
The workable pattern has three parts. Write the limit into the field description (“at most 155 characters”). Validate length in code after the call. Retry once with the over-length value quoted back to the model.
Claude may also return enum values that differ from your list only in capitalisation, per Anthropic’s structured outputs documentation. If your search_intent enum is informational, commercial, transactional, compare case-insensitively before writing to your database.
Claude schemas have complexity limits: 24 optional parameters and 16 union-typed parameters across all strict schemas in a request. Exceeding them returns a 400 “Schema is too complex for compilation”. A single mega-schema for a whole article will hit that.

What Happens When the Output Is Cut Off or Refused?
The guarantee has two holes, and both return HTTP 200. When Claude stops with stop_reason: "refusal" or "max_tokens", the output may not match your schema.
A FAQ block with eight questions can hit a low max_tokens halfway through the sixth answer. The JSON is truncated, your parser throws, and the batch run records a failure that looks like a model problem.
OpenAI surfaces refusals as a separate refusal field instead of schema content, which is easier to branch on. Either way, read the stop signal before you parse.
Set max_tokens to at least twice the expected JSON size, and treat any stop reason other than a normal end-of-turn as a failed call that gets retried, not parsed.
How Do Structured Outputs Interact With Cost and Caching?
Claude injects an extra system prompt describing the format, so input tokens run slightly higher, per Anthropic’s structured outputs documentation. The first call with a new schema also pays a grammar compile delay.
The compiled grammar is cached for 24 hours from last use. Changing the schema structure invalidates it, while changing a name or description does not.
The bigger effect is on prompt caching. Changing output_config.format invalidates the prompt cache for that thread. Our comparison of prompt caching on Claude, OpenAI and Gemini covers why a stable prefix matters.
JSON mode only guarantees valid JSON syntax; structured outputs guarantee the response follows your schema.
– Per OpenAI’s published structured outputs guide
Use structured outputs for shape and a code validator for limits. Gemini can bound numbers and list sizes in the schema; Claude cannot bound strings or numbers at all.
Check the stop reason before parsing, keep one schema per stage, and expect a slower first call.
Frequently Asked Questions
Is JSON mode the same as structured outputs?
No. OpenAI’s structured outputs guide explains that JSON mode only guarantees valid JSON syntax, while structured outputs guarantee the response matches your schema.
Can I enforce a 60-character title limit in the schema?
Not on Claude. Anthropic’s structured outputs documentation lists minLength and maxLength as unsupported. Put the limit in the field description and check the length in code after the call.
What happens if the model refuses or runs out of tokens mid-JSON?
On Claude the response still returns HTTP 200, but with stop_reason refusal or max_tokens the output may not match the schema, per Anthropic’s structured outputs documentation. Check stop_reason before parsing. OpenAI returns a separate refusal field instead.
Why is the first call with a new schema slower?
Both Anthropic and OpenAI compile the schema on first use. Anthropic caches the compiled grammar for 24 hours from last use, so a daily batch pays the compile cost once.
Will changing my schema break prompt caching on Claude?
Yes for that conversation thread. Anthropic’s structured outputs documentation states that changing the output format invalidates the prompt cache, so keep one schema per pipeline stage.
DesignCopy Editorial Team
