Getting model output into parseable JSON usually fails on where the Schema comes from and how you lock it โ not on whether the model will obey. Below: what Structured Output is, why you infer from real JSON, then types, required, and extra fields. Compare OpenAI / Claude / Gemini wrappers, and finish with acceptance and common pitfalls.
Platform wrappers change. The lock order for JSON Schema stays relatively stable. Get the concept and the sample path clear, then talk about how each vendor wraps it.
What is a Structured Output Schema?
A Structured Output Schema is a JSON Schema that constrains the shape of a model's output. It tells the model which fields to return, what type each field is, and which missing keys count as a failure. OpenAI wraps it in json_schema, Gemini uses responseSchema, and Claude and MCP stay closer to a tool's input_schema.
Unlike "just format the JSON," the goal here is stable parse. If the Schema is vague, Validate, Mock, Zod, and Function Calling all drift with it.
Why infer a Schema from a JSON sample?
API docs often lag behind the implementation. A live response tells you whether a price is 199 or "199.00", whether arrays can be empty, and whether a nested object drops a data wrapper. Those details decide whether Structured Output actually works โ not whether the field names merely look right.
Starting from a sample is not the same as letting a tool make product decisions. Inference only reads the structure that is already there; required, enum, and whether extra fields are allowed must be decided by the business.
Three locks: types, required, extra fields
A Schema you can use gets these three right first. pattern, format, and description can wait. If these three are wrong, the whole chain drifts.
1. Infer types from real JSON
Start by checking whether a field is string, number, integer, boolean, array, or object. Email, URL, and date values can also get a format, but don't treat format as the main constraint.
This site's Workbench inference (as of 2026-08-27) has three details you should know:
- In JSON,
199.00parses as the integer199and is labeledinteger, notnumber. - Arrays only sample the first 5 items before types are merged. If item 6 suddenly becomes an object, the generate result will not see it.
- Strings are scanned for email, http(s) URLs, and dates starting with
YYYY-MM-DD.
2. Mark the fields that are truly required
Required is not "this sample happened to have it." It is "the business cannot use the payload without it." Order ids, SKUs, and prices are usually required. Promo tags and subtitles are often optional.
To produce a runnable first draft, the generator puts every key from the sample into required. That is a draft, not a product decision. Drop optional fields before you ship.
3. Decide whether extra fields are allowed
For LLM output, start by turning additionalProperties off. Models love stuffing in extra summary, note, explanation. Once those fields land in the response, downstream parsing gets unstable.
Keep facts and tool behavior separate. OpenAI's official strict Structured Outputs require objects to declare additionalProperties: false. The first draft this site generates from JSON does not add that automatically โ you need to add it before production.
A product sample that is enough to generate a Schema
The sample below is already enough to generate a first draft for OpenAI / Claude / Gemini. Keep price as a number, not "199.00".
{
"name": "ๆ ็บฟ่ณๆบ",
"price": 199.5,
"sku": "HP-1024",
"inStock": true,
"tags": ["audio", "bluetooth"]
}
With this site's current inference rules, this sample yields:
| Field | Infer types | What to do after generate |
|---|---|---|
name |
string | Add description; confirm whether it is required |
price |
number | Write 199.5 here to keep the decimal; 199.00 becomes integer |
sku |
string | Add pattern if you need a format constraint |
inStock |
boolean | Don't let the model return the string "true" |
tags |
string[] | Confirm whether an empty array is legal; don't freeze enum values in one pass |
Once the sample is ready, use the Structured Output tool to generate each platform wrapper in one click, then add descriptions for the business.
How do OpenAI, Claude, Gemini, and MCP wrappers differ?
There should be one core Schema. Platform differences live in the wrapper, not in whether name is a string.
| Platform | Wrapper fields | What to watch when you write it |
|---|---|---|
| OpenAI | type: json_schema + json_schema.schema |
In strict mode, objects usually need additionalProperties: false, and every declared property must appear in required |
| Gemini | responseSchema + responseMimeType: application/json |
Make sure the MIME is JSON first, then talk about field constraints |
| Claude | A tool's input_schema |
is closer to Function Calling: say what the tool does, then constrain the input |
| MCP | inputSchema |
What an Agent sees is a capability description plus an input shape. Don't only drop a bare Schema. |
| Generic JSON Schema | The Draft-07 object itself | Good for validate first, then convert to Zod / OpenAPI |
A typical OpenAI wrapper looks like this. This is a structural sketch โ additionalProperties still needs to be added per the official strict rules:
{
"type": "json_schema",
"json_schema": {
"name": "response_schema",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["name", "price", "sku", "inStock", "tags"],
"properties": {
"name": { "type": "string" },
"price": { "type": "number" },
"sku": { "type": "string" },
"inStock": { "type": "boolean" },
"tags": {
"type": "array",
"items": { "type": "string" }
}
}
}
}
}
What are common pitfalls when generating a Structured Output Schema?
Numbers written as strings
If the sample uses "199.00", the type is inferred as string, and later math or validation will keep failing. Prices, quantities, and scores must be numbers in the sample.
Enums that are too narrow or too wide
Too few enum values and the model can only guess inside a narrow set. Too many and you have no constraint. Start with real business values. Don't write "states we might have later" into the Schema in one pass.
null and a missing field are not the same thing
Optional (the key may be missing) and nullable (the key is present, the value is null) are not the same. A lot of parsers use if (obj.price), which also treats 0 and null as falsy.
Inconsistent array item types
Don't let [1, "2"] sneak into the sample. This site only inspects the first 5 items, and mixed types may collapse into an empty constraint. When you compare two responses, use JSON Diff to inspect the path, then fix the sample.
How do you accept the result after generate?
Don't stop at "it parses." Walk this chain:
- Use JSON โ Schema or the Structured Output tool to generate a first draft.
- Check required, number / integer, and additionalProperties yourself.
- Validate a second real response with Schema validation. The first sample is always optimistic.
- If the frontend uses Zod, convert it with Zod Schema so you don't write two rule sets by hand.
- When API docs need to stay in sync, export OpenAPI 3.1, then add descriptions and error codes.
When validation fails, fix the sample or required first. Don't pile on anyOf just to soften the Schema.
How does this relate to Function Calling, Zod, and OpenAPI?
This article solves one problem: how to get a Schema from JSON that can constrain model output. Nearby capabilities can reuse the same core structure, but they should not become another full tutorial.
- Function Calling: constrains tool input, not the final reply text.
- MCP Tool: standardizes tool capabilities; the input is still JSON Schema.
- Zod / OpenAPI: the same structure serves frontend validation and API docs.
Say what the output should look like first, then decide which wrapper to export.
What should you do next?
If you already have a real response, open the Structured Output tool page, paste the JSON, pick OpenAI / Gemini / Claude / MCP, and make only three manual edits โ required, additionalProperties, and description. Everything stays in the browser and is never uploaded.
If you don't have a real response yet, don't invent a "perfect object." One minimal usable record beats a fake-complete sample stacked with comments.
FAQ
What is a Structured Output Schema?
It is a JSON Schema that constrains the shape of a model's output. The model must return JSON with the declared fields, types, and required keys โ not free text.
Why generate a Schema from a JSON sample instead of writing it by hand?
A real response exposes details docs often get wrong. Infer from a sample, then lock required and additionalProperties yourself. That is usually more stable than inventing a Schema.
How do OpenAI, Claude, and Gemini Structured Output differ?
The core is still JSON Schema; the wrapper fields differ. OpenAI uses json_schema, Gemini uses responseSchema, and Claude / MCP stay closer to a tool input structure. Write the core Schema first, then wrap it.
Can I ship an auto-generated Schema as-is?
No. The generator marks every sample field required, skips additionalProperties by default, and only looks at the first few array items. You must review it and validate a second response.
Should additionalProperties be on or off?
For LLM output, turn it off first. OpenAI strict mode also requires objects to declare additionalProperties: false.
Summary
The right order from a JSON sample to a Structured Output Schema is: live response โ types โ required โ extra fields off โ platform wrapper โ validate with another payload. Tools shorten the first draft. They do not replace product judgment. Keep one core Schema. OpenAI, Claude, Gemini, Zod, and OpenAPI all grow from it.