Structured output and JSON output
Practice this questionOverview
- JSON output is machine-readable data, such as an object with named fields.
- Structured output adds a declared schema so the response follows expected fields and types when the provider supports schema-constrained generation.
- Valid JSON, valid schema, and valid business meaning are three separate checks.
Why this matters
Backend code needs reliable data shapes instead of parsing arbitrary prose.
An everyday example
A claim form with required fields is easier to process than a handwritten letter.
A technical example
{ "intent": "claim_status", "claimId": "C42" } passes a shape check; the backend must still verify that C42 belongs to the signed-in customer.
How it works
- Define schema
- Supply task and schema
- Receive completed output
- Handle refusal/incomplete generation
- Validate locally
- Apply business rules.
Architecture and flow
Natural language → schema-constrained model → runtime validation → business validation → application.
The insurance assistant example
Extract date, claim type, and description from an accident message. Missing fields become null, never guessed dates.
When to use it
Classification, extraction, routing, UI objects, and bounded agent decisions.
When to avoid it
A plain conversational answer may not need a complex schema. Never treat schema adherence as permission to execute a financial action.
Interview answer
“Structured outputs constrain the response shape. I still check refusals, completeness, runtime validity, and business meaning before using the values.”
Benefits, trade-offs, and production considerations
- Prefer provider-supported schemas to prompt-only JSON requests.
- Keep schemas small, use bounded enums, and validate independently at trust boundaries.
- JSON mode may provide syntactically valid JSON without enforcing your fields.
- Official OpenAI structured output guide.
// Study example: server-side Node.js; packages openai and zod.
// LLM_MODEL must identify a model supporting the required schema feature.
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const client = new OpenAI(); // Reads server-side OPENAI_API_KEY.
const Intent = z.object({
intent: z.enum(["claim_status", "policy_question", "other"]),
claimId: z.string().nullable(),
});
const model = process.env.LLM_MODEL;
if (!model) throw new Error("Configure LLM_MODEL");
const result = await client.responses.parse({
model,
store: false,
input: [
{ role: "system", content: "Classify the request. Never invent a claim ID." },
{ role: "user", content: "What happened to claim C42?" },
],
text: { format: zodTextFormat(Intent, "insurance_intent") },
});
if (result.status !== "completed" || !result.output_parsed) {
throw new Error("No completed structured result; handle refusal or failure");
}
const intent = Intent.parse(result.output_parsed);
// intent selects an allowed route. It grants no customer permissions.zodTextFormat converts the schema into the request format; responses.parse returns parsed data when available. store: false controls API response storage for this request; it does not by itself establish all provider retention or compliance properties. Pin compatible SDK versions and consult the linked guide before using the snippet in an application.