Stop Asking Nicely For JSON — Define a Schema Instead
Ask an AI for JSON, and you're gambling. Ask for a field nested two levels deep, and it might flatten it. Ask for exactly three keys, and it might add a fourth "helpful" one you never requested. You end up writing defensive parsing code to catch what the model didn't quite give you. None of that is necessary once you stop describing the shape in English and start defining it as data.
The problem with prompting for structure
"Please respond in valid JSON with fields name, email, and orders" reads like a spec, but the model treats it like any other instruction: a strong suggestion, not a contract. In practice this breaks in predictable ways — a nested field gets flattened or renamed, an unrequested description or note key shows up because the model thought it was being helpful, or a field the model was unsure about gets omitted rather than left null. Each of these is a runtime surprise your code has to detect and handle after the fact.
The root cause is that natural-language format instructions are just text tokens mixed in with everything else in the prompt. The model has no mechanism forcing it to obey them — it's pattern-matching on "this looks like a JSON-shaped request," not executing a schema.
Why schema mode actually works
Structured outputs flip the mechanism. Instead of describing the shape in words, you hand the model call a real schema object — a Zod schema, a Pydantic model, or a raw JSON Schema document — through a parameter built for exactly this purpose. The model provider then constrains generation itself, or validates and retries, so the response conforms to that schema before your application code ever sees it. You're not hoping the model understood your description; you're handing it a contract it's mechanically bound to.
This differs from format instructions in three concrete ways:
- Types are enforced, not suggested. A field typed as a number can't come back as the string
"42". - Required fields can't silently disappear. The enforcement point is the generation/validation step, not a hopeful regex on your end.
- Field-level guidance moves into the schema. Instructions like "under 200 characters, general audience" become a description on the schema field itself instead of prompt boilerplate.
How to do it
Most modern AI SDKs expose a "generate structured output" or "generate object" call that takes your normal prompt plus a schema parameter, separate from the prompt text:
schema = {
name: string,
email: string,
orders: [{ id: string, total: number }]
}
result = model.generateObject({
prompt: "Extract the customer record from this email...",
schema: schema,
})
# result.object is validated — no parsing, no defensive code
The pattern is the same across providers and libraries: define the schema once, pass it alongside the prompt, and read back a validated object instead of a raw string. Many SDKs also expose a strict mode that hard-constrains generation to the schema rather than validating-and-retrying after the fact — worth turning on if your library supports it.
Where this pays off
- Extracting structured data from unstructured text — pulling a customer record, an invoice, or a resume out of free-form input.
- API responses that downstream code depends on — no more guard clauses because a key might be missing.
- Classification and routing — sorting support tickets, tagging content, picking a tool to call. An enum-typed field means the model literally cannot return a category outside your list.
Power tricks
- Don't trust a published benchmark for your schema. A model that hits high schema compliance on a vendor's eval set can still misbehave on your data — unusual nesting depth, field-name patterns, or domain-specific enums are exactly where models diverge from benchmarks. Test against real inputs before shipping.
- A schema validates shape, not meaning. The model can return a syntactically valid but factually wrong value. Schema mode kills a class of parsing bugs, not hallucination.
- Keep schemas tight. A large schema with vague field names gives the model less signal than a focused one with clear per-field descriptions — treat schema design as prompt design.
Resources
- Structured Outputs / JSON Schema-constrained generation is documented across major AI SDKs and provider APIs — see your provider's "structured outputs" or "generate object" docs.
- Zod (TypeScript) and Pydantic (Python) are the most common schema libraries paired with these APIs.
Building an AI feature? Yeda AI designs, audits, and ships production LLM systems.