All three chat windows love speaking like humans; all three API docs write the contract as JSON. This piece is dated 2026-09-05 and does not guess the next format โ only paths that can already go to production: OpenAI Structured Outputs, Claude's output_config / input_schema, Gemini's responseSchema, and MCP's JSON-RPC. Below: first why JSON, then each vendor's wrapper, then one cross-platform sample that is enough to generate a Schema.
"Loves JSON" sounds like a taste. For a model, it is whether the next hop can catch the interface. People can read a fluent paragraph; databases, frontends, billing, and agent loops cannot. The 2026 flagships โ GPT-5.6, Claude Fable 5.1, Gemini 3.8 Flash โ sit on different product lines (see the previous piece 2026 AI model war), but when they hand results to a program they take the same path: a parseable object, plus a Schema.
What models actually need is not curly braces
Free text is good for explaining. It is a bad contract. Miss a quote, write true as "yes", write an amount as "about twelve bucks", and downstream has to write regex, retries, and a human fallback. JSON was chosen not because RFC 8259 is elegant, but because it does four things at once:
- It parses. Every language, every SDK, every browser already has a parser. Failure is a syntax error, not "it feels off."
- It validates. JSON Schema can write type, enum,
required,additionalProperties. The model can be constrained at generation time; the server can check again. - It nests. Objects, arrays, booleans, numbers, and null cover tool parameters and business documents. You do not have to invent a new tree first.
- Training data is full of it. API responses, config files, logs,
application/jsonon the web โ models have seen far more valid JSON than valid YAML or XML.
YAML is allergic to indentation; comments and multi-docs also fork parsers. XML tags are heavy; namespaces make Schemas long. Markdown tables are for people, not for programs as input. So all three write "structured" as: the output must be JSON, and the shape must match a Schema.
The shape can be right and the values still wrong. Constrained decoding guarantees keys and types, not "unit price ร qty = total." Google's own docs say this plainly. It applies to all three: the Schema passed; business rules still need another check.
Chat, API, tools: all three layers are converging
The same product actually has three output layers. Mix them, and it feels like "the model sometimes listens, sometimes doesn't."
| Layer | For people | For programs |
|---|---|---|
| Chat window | Explanations, drafts, sentences with tone | Almost no contract; copy it out and you still have to edit by hand |
| Structured Output | Optional | The whole reply is one JSON object |
| Function Calling / tools | The model says "I need to call this tool" | Parameters must match parameters / input_schema |
In 2024 you could still get by with a prompt that said "return JSON only." In 2026 that path is debt. JSON Mode only guarantees the braces parse; it does not guarantee the fields are there. The production path is constrained decoding: illegal tokens are blocked at sample time. For the tutorial write-up, see Generate Structured Output from a sample; for the agent-side tool loop, see DevDay 2026 Agent.
How each of the three "likes" JSON
What they like is the same object, not the same request body. Write the wrapper into the docs; leave the fields in a shared file.
1. ChatGPT / OpenAI: the Schema goes into the decoder
In Chat Completions, Structured Outputs hang off response_format, type json_schema; production should turn on strict: true. The Responses API puts the same object on text.format. Paste fields from an old guide onto the new API and you often don't get a nice error โ it just stops constraining the way you expected. The SDK's .parse() takes another pass with Pydantic / Zod.
The tool side is a second contract: a function's parameters are also JSON Schema. Programmatic Tool Calling lets the model fire several tool rounds on the server; what goes in and out is still objects, not a paragraph. JSON Mode (parse-only) can stay in demos; don't leave it on billing or write paths.
2. Claude: tool parameters are the contract
Anthropic writes "give me an object" and "go call a tool" as the same shape. To ask for JSON directly, use the Messages API's output_config.format (the old name output_format is deprecated). The agent path adds input_schema to the tool and turns on strict: true on the tool definition โ not on tool_choice.
The Schema likewise wants additionalProperties: false and a complete required list. What you get: for the tool the model picked, parameters are constrained at generation time. The SDK's client.messages.parse() checks for you and does not hand a raw string to the business layer.
3. Gemini: mime type plus Schema
Gemini folds JSON Mode and Structured Output into one path: response_mime_type: application/json, then hang responseSchema / response_json_schema. It looks the most "Schema-native," and the subset is the narrowest: basic types, enum, format, bounds, and required are available; deep polymorphism, recursive $ref, and trees that are too large or too deep โ the docs say they may be rejected outright.
High-volume Structured Output still often picks Gemini 3.8 Flash; see Pick a model by task. Output cap 64K; chunk long documents first. Gemini 4 has no release date; keep writing the production path as 3.x. Details: When will Gemini 4 be released.
One layer further out: MCP, evals, routing
Outside the model vendors, JSON is already the bus for agent runtimes.
- MCP uses JSON-RPC to describe tools. Tool names, parameters, and return values are all objects. This site's MCP Tool page is writing that contract, not a prompt.
- Evals and traces need to be diffable. A paragraph cannot be compared automatically; a JSON document can use JSON Diff to show whether a field drifted or a type drifted.
- Model routing itself can be JSON: task, constraints, candidate
model_id, selected reason. The previous piece already gave a routing sample. A generation swap changes the ID, not the field names.
So "JSON is becoming AI's common data format" is not a slogan. It means: the prompt can be natural language; the boundary must be an object. Who generates the object can change; what the object looks like cannot rest on a verbal agreement.
A common format is not "any JSON"
Treat any curly braces as a contract and it still blows up in three months. JSON that survives across models usually has five hard rules:
- Lock the types. Booleans are
true/false, not "yes". Numbers are number, not"0.75". - Close the enums. Status, reason, priority become an enum. Free text is only for sentences you actually display.
- List every
required. All three strict modes want you to list required fields explicitly. Miss one and you allow a missing field. additionalProperties: false. Otherwise the model invents keys your parser does not know.- One sample, three wrappers. Maintain fields once. OpenAI / Claude / Gemini request bodies are generated from the same Schema.
Gemini's Schema language is an OpenAPI subset. Start with the intersection: objects, arrays, string / number / integer / boolean, enum, required. Leave oneOf, recursive refs, and extra-deep nesting until you confirm that platform can swallow them.
A sample that works across all three
Below is business JSON for "extract an invoice." It is not a request wrapper; it is the object all three models should emit. Enums as strings, amounts as number, tax-included-or-not as boolean.
{
"doc_type": "invoice",
"currency": "CNY",
"vendor": "Example Labs",
"invoice_id": "INV-20260905-018",
"issued_on": "2026-09-05",
"line_items": [
{
"sku": "schema-review",
"qty": 2,
"unit_price": 480,
"amount": 960
}
],
"subtotal": 960,
"tax": 96,
"total": 1056,
"tax_included": false,
"confidence": 0.86,
"needs_review": false
}
With this site's inference rules, that sample yields:
| Field | Infer types | What to do after generate |
|---|---|---|
doc_type / currency |
string | Collapse to an enum; don't leave free text |
qty / amounts / confidence |
number | Writing "960" drifts to string; add 0โ1 bounds on confidence |
tax_included / needs_review |
boolean | Samples must be true / false |
line_items |
array of object | Every item needs sku, qty, amount |
issued_on |
string | Add format: date; don't let the model output "September 5" |
Once the sample is ready, open Structured Output to generate the OpenAI / Claude / Gemini wrappers, then review required and additionalProperties by hand. The same object can also become a tool via Function Calling: the model is not "talking about an invoice"; it is submitting a document that must validate.
How to accept it in JSON Toolbox
- Paste the sample above into JSON Format and confirm it parses.
- Generate a first draft with Structured Output or JSON โ Schema.
- Take a second set of real model output to Schema validation. The first sample is always a bit too clean.
- When you switch from GPT to Claude or Gemini, use JSON Diff to see whether a field dropped or a type drifted.
- Convert to Zod when the frontend needs checks, and to OpenAPI 3.1 when you need API docs.
Everything stays in the browser and is never uploaded.
FAQ
Why do large models prefer JSON over YAML or XML?
Parsers, the Schema ecosystem, and training data all land on JSON. YAML fears indentation; XML is too heavy. All three contracts are written as JSON Schema.
What is the difference between JSON Mode and Structured Output?
JSON Mode only guarantees it parses. Structured Output constrains decoding against a Schema. Production uses the latter.
Can the three vendors share one Schema?
Fields can be shared; wrappers cannot. Generate three request bodies from the same sample.
Does a valid Schema mean the business is correct?
No. The shape can be right and the total still wrong. A second set of real output must be checked again.
Do you need to rewrite the JSON contract when you swap models?
No. Lock the fields; swap model_id and the wrapper. Routing itself can be JSON; see 2026 AI model war.
Summary
ChatGPT, Claude, and Gemini love JSON because a program has to catch the model โ it cannot rely on a well-written paragraph. The three wrappers differ: response_format / text.format, output_config / input_schema, responseSchema. What they share is fields, types, required, and "no extra keys." MCP, evals, and routing also travel as objects. What survives next week's generation swap is the sample and the Schema, not "please return JSON" in a prompt. Grow the contract from one sample; validation, Zod, and OpenAPI all follow it.