JSON to OpenAI
The result appears here.
Generate
Your document never leaves the browser.
A strict Structured Outputs schema for OpenAI, from an example answer — in your browser.
Structured Outputs makes an OpenAI model answer in exactly the JSON shape you give it. Paste an example of the answer you want and this page writes the schema in the strict dialect OpenAI accepts, so you do not have to learn the rules by trial and error.
In strict mode, OpenAI wants every property of every object listed as required, and every object closed with additionalProperties: false. So a key your sample lacked in places cannot simply be optional. Here gift-wrap is listed as required and its type becomes ["boolean", "null"]: the model always sends the key, and sends null when it has nothing to say.
The list under the result names each change it made, with its path. For this sample it is one line, saying one optional field was made nullable at $.items[]["gift-wrap"]. The nested objects are written once under $defs and referred to with $ref, which strict mode supports.
The sample, an order with two line items, pasted as the source
{
"order_id": 1042,
"placed_at": "2026-09-25T10:15:00Z",
"paid": true,
"customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"items": [
{ "sku": "PEN-01", "qty": 2, "price": 3.5, "note": null },
{ "sku": "INK-07", "qty": 1, "price": 12, "note": "Fragile", "gift-wrap": true }
]
}The schema written for it
{
"type": "object",
"properties": {
"order_id": {
"type": "integer"
},
"placed_at": {
"type": "string"
},
"paid": {
"type": "boolean"
},
"customer": {
"$ref": "#/$defs/Customer"
},
"items": {
"type": "array",
"items": {
"$ref": "#/$defs/Item"
}
}
},
"required": [
"order_id",
"placed_at",
"paid",
"customer",
"items"
],
"additionalProperties": false,
"$defs": {
"Customer": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
}
},
"required": [
"name",
"email"
],
"additionalProperties": false
},
"Item": {
"type": "object",
"properties": {
"sku": {
"type": "string"
},
"qty": {
"type": "integer"
},
"price": {
"type": "number"
},
"note": {
"type": [
"null",
"string"
]
},
"gift-wrap": {
"type": [
"boolean",
"null"
]
}
},
"required": [
"sku",
"qty",
"price",
"note",
"gift-wrap"
],
"additionalProperties": false
}
}
}An answer and a score
{ "answer": "yes", "score": 0.9 }With Output Request fragment and API Chat Completions
{
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "root",
"strict": true,
"schema": {
"type": "object",
"properties": {
"answer": {
"type": "string"
},
"score": {
"type": "number"
}
},
"required": [
"answer",
"score"
],
"additionalProperties": false
}
}
}
}Option
Output: Schema, the default, writes the bare schema. Request fragment wraps it in the part of the request body that carries it, with strict set to true.
Option
API, shown for a fragment: Responses API, the default, which puts the schema under text.format, or Chat Completions, which puts it under response_format. Mistral, Groq, xAI and other OpenAI-compatible APIs take the Chat Completions shape.
Option
Name, shown for a fragment: the schema name the request carries. It defaults to your root name in snake_case.
A root that is not an object, such as a list of records, is wrapped as a required property named items, because OpenAI’s root must be an object. A value the inference could not type is sent as a string, and the list says where.
Three of OpenAI’s published limits are checked as you type: 5,000 object properties in one schema, 10 levels of nesting, and 120,000 characters of property and definition names. A warning appears under the schema when any of them is exceeded.
A list of records as the root
[
{ "id": 1 },
{ "id": 2 }
]Wrapped as items, and the list under the schema says so
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/$defs/RootItem"
}
}
},
"required": [
"items"
],
"additionalProperties": false,
"$defs": {
"RootItem": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
],
"additionalProperties": false
}
}
}Inference and code generation both run inside this browser tab. The sample is never uploaded, stored on a server or logged, because the page has no server to send it to, and once loaded it carries on working with the connection off.
No. It writes the schema in this tab; you send it with your own key from your own code, and neither the sample nor the key ever reaches this site.
Strict mode requires it. A field that may be missing is instead allowed to be null, which carries the same meaning.
Yes. It is valid JSON Schema, only stricter than it needs to be; for a plain JSON Schema of the sample, use the JSON Schema page.