Structured Outputs for Beginners: The Playbook for Getting Clean JSON from AI
Structured outputs for beginners: a simple playbook to get clean, valid JSON from any AI model every time, with schemas, code checks and real tests.

It is 11 at night in Pune, and Meera’s support tool has stopped working again. Her app sends each customer email to an AI model and asks for a small piece of JSON back: the category, how urgent it is, and the order number.
Most nights it works. Tonight the model replied with “Sure! Here is the JSON you asked for:” and then the data. Her code expected only the data, so it crashed.
Meera does not need a smarter model. She needs the model to fill in a form, every single time. That is what structured outputs are for, and this guide is structured outputs for beginners: what they are, why plain prompting is not enough, and five plays to get clean, reliable JSON from any AI model.
Last verified: 13 November 2026. AI tools change fast; check the linked sources for anything newer.

Who this is for: this structured outputs for beginners guide is for anyone who calls an AI model from code and wants answers a program can read, not just a human. You should know what a prompt is (see our prompt engineering playbook). Time needed: about 30-40 minutes.
Structured outputs for beginners: what they are, in simple words
Think of a bank form. If you ask a person to “write down your details”, you get a paragraph in any order. If you hand them a form with boxes for name, account number and date, every answer lands in the right box. The form is what makes the answers easy to process.
An AI model normally writes free text, like the person with a blank page. Structured outputs hand the model a form. In precise terms: you give the model a JSON Schema (a written description of the fields, their types and which ones are required), and the AI provider makes sure the reply follows it.
JSON is simply a text format programs use to pass data around, like {"category": "refund", "urgent": true}. Each item has a name (a “key”) and a value.
JSON mode vs structured outputs
Many tools also offer an older “JSON mode”. It promises the reply is valid JSON, but not that it has the fields you wanted. OpenAI’s documentation says both give valid JSON, but only structured outputs make the reply follow your schema, and it recommends structured outputs when available.
So there are three levels: asking nicely in the prompt (weakest), JSON mode (valid JSON, any shape), and structured outputs (valid JSON in your exact shape). This playbook aims for the third, with a safety net for models that do not support it.
The playbook at a glance
Here is the whole structured outputs for beginners playbook in five plays.
- Design the form on paper: list the fields your code really needs.
- Write the schema: turn that list into a small JSON Schema.
- Switch on the provider’s structured output mode: let the API enforce the shape.
- Check the answer in code anyway: handle refusals, cut-off replies and business rules.
- Test with messy real inputs: keep a small test list and rerun it after changes.
Play 1: Design the form on paper
Goal: know exactly what your program needs before you touch the model.
- Write down what your code does with the answer (save it, route it, show it).
- List only the fields that job needs. Fewer fields means fewer mistakes.
- For each field, pick a type: text, number, true/false, or a list.
- Where only a few answers make sense, write them out (for example: refund, delivery, login, other).
- Mark which fields can be missing, such as an order number the customer forgot.
Meera’s list fits on a sticky note: category (one of four), urgent (true/false), order ID (text, or empty if missing) and a one-line summary.
You are done when: you can describe every field and its allowed values in one short list.
Play 2: Write the schema
Goal: turn the sticky note into a JSON Schema the model and your code can both read.
{
"type": "object",
"properties": {
"category": { "type": "string", "enum": ["refund", "delivery", "login", "other"] },
"urgent": { "type": "boolean" },
"order_id": { "type": ["string", "null"] },
"summary": { "type": "string" }
},
"required": ["category", "urgent", "order_id", "summary"],
"additionalProperties": false
}In plain steps, this schema says:
- The answer is one object (one filled-in form).
enummeans “pick one of these words only”, so no surprise categories.["string", "null"]means “text, or null if there is none”. This is how you show an optional value.requiredlists every field, andadditionalProperties: falsemeans “no extra boxes”.
The last two lines matter. OpenAI’s examples list every field as required and set additionalProperties to false, and Anthropic’s docs say additionalProperties: false is required for objects.
You are done when: your schema has every field from Play 1, with clear types and allowed values.
Play 3: Switch on the provider’s structured output mode
Goal: let the API enforce the shape, instead of hoping the prompt works.
- Check your model supports structured outputs. Not every model does.
- Pass your schema in the provider’s setting. In OpenAI’s Responses API it is
text.formatwithtype: "json_schema"andstrict: true. In Anthropic’s Claude API it isoutput_config.formatwithtype: "json_schema". - If you use Python or TypeScript, try the SDK helpers. Anthropic’s
messages.parse(), for example, accepts a Pydantic model or Zod schema and returns the checked result. - Keep a short instruction in the prompt too (“Classify this support email”), so the model knows the job, not just the form.
Parameter names differ between tools and change over time, so treat the names above as an illustration and check your provider’s current docs. Other large providers, such as Google’s Gemini, offer similar options.
No structured output support? Fall back to: describe the JSON in the prompt, show one example, parse the reply, and retry once if it breaks. It works, but it is the weakest level.
This is the biggest single step in structured outputs for beginners. Meera moves her schema from the prompt into the API setting. The “Sure! Here is the JSON” line disappears, because the model is no longer allowed to write anything outside the form.
You are done when: ten test calls in a row return JSON your code parses without any clean-up.
Play 4: Check the answer in code anyway
Goal: catch the cases the schema cannot.
A correct shape is not the same as a correct answer. The form can be filled in neatly and still say the wrong thing. OpenAI’s guide is clear that your app must still handle refusals, incomplete replies, API errors and business rules the schema cannot express.
- Refusals: if the model declines for safety reasons, the reply may not follow your schema. Check for a refusal before parsing.
- Cut-off replies: if the answer hit the length limit, the JSON may be unfinished. Check the stop reason and raise the limit.
- Business rules: validate what the schema cannot say, for example “order IDs start with ORD-“.
- Validation: parse the reply into a typed object (Pydantic in Python, Zod in TypeScript, a record class in Java) so bad data fails loudly.
Meera adds one rule: if order_id does not start with “ORD-“, set it to null and flag the ticket for a human.
You are done when: a refusal, a cut-off reply and a bad order ID each lead to a clear, handled outcome instead of a crash.
Play 5: Test with messy real inputs
Goal: prove the form works on the emails real customers send.
- Collect 15-20 real (anonymised) inputs, including odd ones: empty messages, two orders in one email, mixed Hindi and English, angry all-caps.
- Write the answer you expect next to each one.
- Run them all and count how many fields match.
- Rerun the list after every prompt, schema or model change.
This is a tiny eval. Our AI evals playbook shows how to grow it. Meera finds that emails with two orders confuse the model, so she adds a note to the prompt: “If there are several orders, use the first one.”
You are done when: your test list passes, and you rerun it before every release.
Do you need structured outputs or something else?
| Option | What you get | Choose it when |
|---|---|---|
| Plain prompt (“reply in JSON”) | Usually JSON, sometimes extra text or missing fields | Quick experiments, or the model has no other option |
| JSON mode | Valid JSON, but any shape | Older models where schema support is missing |
| Structured outputs | Valid JSON in your exact schema | Your code reads the answer: forms, extraction, classification |
| Function calling | The model asks your code to run a tool, with structured inputs | The model needs to take an action or fetch data |
Function calling and structured outputs are cousins. If the model needs to do something, read our function calling playbook. If it only needs to answer in a fixed shape, structured outputs are simpler.
Structured outputs for beginners: mistakes to avoid
- Trusting the prompt alone. “Reply only in JSON” works most of the time, which is exactly why it fails at 11 at night. Fix: use the API’s structured output setting.
- A giant schema. Thirty fields invite wrong answers. Fix: ask only for what your code uses, or split the job into two calls.
- Forcing an answer that may not exist. If a field is required and has no “null” option, the model may invent an order number. Fix: allow null for anything that can be missing.
- Using unsupported schema features. Providers support only part of JSON Schema. Anthropic’s docs, for example, list number limits like
minimumandmaximumas unsupported, and they return an error. Fix: keep schemas simple and check limits in your own code.
How to know it is working
- Parse errors in your logs drop to zero (see our LLM observability playbook for logging).
- Your code has no clean-up step that strips extra text or code fences.
- Your test list from Play 5 passes after every change.
- Refusals and cut-off replies appear as handled cases, not crashes.
Your structured outputs for beginners checklist
- ☐ I listed only the fields my code needs, with types and allowed values.
- ☐ My schema marks every field required, allows null for optional ones and blocks extra fields.
- ☐ I pass the schema through the provider’s structured output setting, not just the prompt.
- ☐ My code handles refusals, cut-off replies and business rules.
- ☐ I parse into a typed object and fail loudly on bad data.
- ☐ I have a test list of messy real inputs and rerun it after changes.
Frequently asked questions
What are structured outputs in an LLM?
They are a feature that makes a large language model reply in a fixed format, usually JSON that matches a schema you provide. Your code can then read the answer directly, without guessing where the data starts. In structured outputs for beginners terms: the model fills in a form instead of writing a letter.
Is JSON mode the same as structured outputs?
No. JSON mode only promises valid JSON. Structured outputs also make the reply follow your schema, with the fields and allowed values you defined.
Can structured outputs still be wrong?
Yes. The shape is guaranteed, but the content is still the model’s best guess. A neatly filled form can hold the wrong category, which is why Plays 4 and 5 exist.
Do I need to write JSON Schema by hand?
Not always. Many SDKs build the schema from a class, such as a Pydantic model in Python or a Zod schema in TypeScript. Java developers can see the same idea in our Spring AI structured outputs guide.
Do structured outputs make calls slower or cost more?
A little, at first. Anthropic’s docs say the first request with a new schema has extra delay while it is prepared, then it is cached for 24 hours after last use, and the format adds some input tokens.
Back to Meera, and your next step
A week later, Meera’s support tool has sorted a few thousand emails (an illustrative number) without a single parse error. The odd ones, like a refusal or a strange order ID, land in a small “needs a human” queue instead of crashing the app. She sleeps through the night.
That is the whole idea of structured outputs for beginners: give the model a form, then check what comes back. Your next action: pick one place where your code reads an AI reply, write a four-field schema for it, and switch on structured outputs today. Then let the model take actions with the function calling playbook, or revisit how LLMs work to see why free text drifts in the first place.
Sources: OpenAI Structured Outputs guide (JSON mode vs schema adherence, refusals, text.format), Anthropic Claude structured outputs docs (output_config.format, supported schema features, caching), and OpenReplay on JSON Schema for LLM structured outputs.


