Phase 4 · Structured & Reliable OutputModule 14~34 min read

Structured Output: JSON & Schemas

To wire a model into software, its output must be machine-readable. Get clean JSON every time with schemas, examples, and the model's structured-output modes.

What you'll learn

The moment a model's output feeds into software instead of a human, it has to be machine-readable. A chatty paragraph is useless to a program; a clean JSON object is gold. This module is about getting reliable structured output — JSON that parses every time.

By the end of this module you'll be able to:

  • Explain why free-text output breaks automated pipelines
  • Prompt for clean JSON and describe the exact schema you need
  • Constrain fields to controlled values with enums
  • Validate and repair output so a bad response can't crash your app

Why free text breaks pipelines

Imagine your code expects the model to return a category it can store in a database. If the model replies "Sure! This looks like a billing issue 😊," your parser has to dig the word out of a sentence that changes shape every time. Multiply that by thousands of calls and you have a fragile system. Structured output removes the guesswork: the program knows exactly where each value lives.

Asking for JSON

The first step is simply to ask — explicitly, and with an example of the shape. Say "return only JSON," forbid extra prose, and (from Module 9) consider prefilling the opening brace to stop preamble.

Prompt

Classify this message as billing, bug, or praise. Return only JSON like {"category": "..."} with no other text. Message: "The new dashboard is gorgeous!"

AI response

{"category": "praise"}
Explicitly asking for JSON-only output — with a shape example — gets a response your code can parse directly.

Describing a schema

For anything beyond one field, spell out a schema: the field names, their types, and their formats. The more precisely you describe the shape, the more reliably the model fills it — including tricky details like date formats and which fields may be null.

extract-event.txt
Extract the event details from the message below.
Return ONLY JSON matching this schema, no prose:

{
  "title":    string,
  "date":     string in YYYY-MM-DD,
  "start":    string in 24h HH:MM,
  "location": string | null,
  "online":   boolean
}

Message: "Let's do the design review next Tuesday (Mar 4) at 2pm, over Zoom."
A written schema pins down field names, types, and formats — so '2pm' becomes '14:00' and 'over Zoom' sets online: true.

Key idea

Treat the schema as a contract. State field names, types, formats (dates, units), and nullability explicitly — every detail you leave vague is a place the output can vary between calls.

Enums & controlled vocabularies

When a field must be one of a fixed set of values, say so. An enum ("one of: low, medium, high") stops the model from inventing synonyms like "moderate" or "urgent-ish" that would break downstream code expecting exact matches.

Without an enumWith an enum
“priority”: “kind of urgent”“priority”: “high” (one of: low | medium | high)
“sentiment”: “pretty good”“sentiment”: “positive” (positive | neutral | negative)
“status”: “all done!”“status”: “complete” (open | in_progress | complete)
Constrain free-form fields to a fixed vocabulary so every value is one your system already understands.

JSON modes & validation

Many APIs now offer a structured-output or JSON mode that forces responses to be valid JSON — often against a schema you supply. Use it when available; it's far more reliable than asking politely. But never trust output blindly: always parse and validate before acting on it.

validate.py
import json

raw = call_model(prompt)          # the model's text output

try:
    data = json.loads(raw)        # 1. parse
except json.JSONDecodeError:
    data = repair_or_retry(raw)   # 2. handle bad JSON

# 3. validate the shape before trusting it
assert set(data) >= {"title", "date", "start", "online"}
assert isinstance(data["online"], bool)

save_event(data)
The defensive pattern: parse, handle parse failures, and validate the shape before your app relies on the data.

Watch out

Even in JSON mode, a value can be missing, the wrong type, or out of range. Validate the shape and the content — not just that it's syntactically valid JSON. We'll extend this into full reliability engineering in Module 17.

Recap & quick check

Key takeaways

  • When output feeds software, it must be machine-readable — free text is fragile to parse.
  • Ask explicitly for JSON, forbid extra prose, and show an example of the shape.
  • Describe a full schema (names, types, formats, nullability) — treat it as a contract.
  • Use enums to constrain fields to a fixed vocabulary so values always match your code.
  • Prefer a JSON/structured-output mode when available, but always parse AND validate before trusting output.

Quick check

1. Why is free-text output a problem for automated pipelines?

2. What's the benefit of describing a full schema rather than just saying 'return JSON'?

3. Why constrain a field with an enum like 'low | medium | high'?

4. You're using the API's JSON mode. What must you still do?

Structured output controls the shape of a response. Next we control its behavior — the rules and guardrails that keep a model on task. Next up: Module 15 — Constraints, Rules & Guardrails.