Skip to content
AIMODELRACE

Module 4 of 11 · Advanced · 10 min read

Structured output: JSON and schemas

Get machine-readable output you can rely on, design schemas that help the model, and validate everything.

Key takeaways
  • 1Schema-constrained output (structured outputs, JSON mode, function calling) beats asking nicely.
  • 2Valid JSON is not the same as correct JSON: validate values, not just shape.
  • 3Give the model an honest way out: nullable fields and 'unknown' values.
  • 4Field order matters: put evidence fields before conclusions.

01Three levels of structure

There are three increasingly reliable ways to get structured output.

  • Describe the format in prose: fine for chat, unreliable for software.
  • Show an example of the exact output: much better, still occasionally broken.
  • Use your API's schema feature (often called structured outputs, JSON mode or function calling): the model is constrained to produce output that matches your JSON Schema.
Tip
If code will parse the output, use the schema feature. Reserve prose-described formats for humans reading the result.

02Designing a schema that helps the model

A schema is also a prompt. Field names and descriptions tell the model what you mean, so make them descriptive. Use enums for categories so the model cannot invent new labels. Keep nesting shallow; deeply nested structures are harder to fill correctly.

Because models generate output in order, the order of fields matters. If you want the model to consider evidence before deciding, put an 'evidence' field before the 'decision' field.

Example
{ "type": "object", "properties": { "evidence": { "type": "string", "description": "Quote the sentences from the contract that matter." }, "has_auto_renewal": { "type": ["boolean", "null"], "description": "null if the contract does not say" }, "notice_period_days": { "type": ["integer", "null"] }, "risk": { "type": "string", "enum": ["low", "medium", "high", "unclear"] } }, "required": ["evidence", "has_auto_renewal", "notice_period_days", "risk"], "additionalProperties": false }

03Give the model an honest way out

If every field is required and non-nullable, the model must put something in it, even when the source has no answer. That is a recipe for invented values. Allow null, add an 'unclear' enum value, or include a 'not_found' list, and say in the prompt that these are correct answers when the information is missing.

04Worked example: an extraction prompt

Pair the schema with a short prompt that explains the job and the rules for missing data.

Example
Extract the key terms from the contract below into the schema provided. Rules: - Use only what the contract states. If a term is missing or ambiguous, use null or 'unclear' and explain in evidence. - Quote exact wording in evidence so a reviewer can check it quickly. - Do not interpret the law; just report what the text says. <contract> {{contract text}} </contract>

05Validate, then retry

Even with schemas, validate in code: check types, ranges, that dates parse, that IDs exist, that totals add up. When validation fails, send the error back to the model with the original input and ask it to fix only the problem. One or two retries usually suffice; if it still fails, route to a person or a fallback.

  • Shape checks: enforced by schema mode, still worth asserting.
  • Value checks: ranges, formats, cross-field consistency.
  • Source checks: does the evidence quote actually appear in the document?

06Pitfalls

Structured output solves parsing. It does not solve correctness.

  • Trusting valid JSON: a perfectly formatted object can still contain a hallucinated number.
  • Giant enums: hundreds of options dilute attention. Narrow first with a routing step.
  • Mixing prose and JSON: if you need both, ask for JSON with a 'summary' string field rather than text around the JSON.
  • Provider differences: supported schema keywords and limits vary, so check your provider's documentation.

Finished reading?

Mark it complete to track your progress, then test yourself with the Advanced Prompting quiz.