Structured output vs JSON mode vs function calling: what is the difference?
Advertisement
🧩 Scenario
Concept Walkthrough
Three different promises
Think of it like TypeScript levels of safety.
- JSON mode is like
JSON.parsesucceeding. You know the text is valid JSON. You do not know iftitleexists or ifsalaryis a number. It is theanyof the three. - Structured output is like a typed API response. You send a JSON Schema, and the provider constrains generation so the reply follows that schema. Anthropic describes its version as compiling the schema into a grammar, which is why the first request with a new schema has extra latency (both OpenAI and Anthropic document this).
- Function calling (tool calling) uses a schema too, but for the arguments of a function. The model does not answer the user. It returns "please call
searchJobswith these arguments", your server runs it, and the result goes back to the model.
Who reads the output?
This is the simplest way to choose. If your UI or database reads the result directly (a form, a card, a list), use structured output. If your code needs to do something before the model can answer (look up data, call an API, write to a database), use a tool. OpenAI's guide frames it the same way: tools connect the model to your functions and data, a response format shapes the reply to the user.
Strict schemas have rules
For strict mode, OpenAI's examples set additionalProperties: false, list every property in required and express "optional" as a union with null. So you write salary: z.number().nullable(), not .optional(). Anthropic's SDK helpers remove constraints such as minimum and maxLength from the schema they send and check them after the response instead.
Strict is not the same as guaranteed
Two cases still break the shape. A refusal: Anthropic notes the refusal message takes precedence over schema constraints, and you still get a 200. A token limit: if output stops at max_tokens, the JSON may be incomplete. That is why you still validate.
Key Code Explained
import { generateText, Output, NoObjectGeneratedError } from 'ai';
import { z } from 'zod';
import { chatModel } from '@/lib/models';
const jobSchema = z.object({
title: z.string(),
location: z.string().describe('City, or "Remote"'),
// nullable, not optional: strict schemas want every key present
salaryLakhsPerYear: z
.object({ min: z.number(), max: z.number() })
.nullable(),
skills: z.array(z.string()),
});
export async function extractJob(description: string) {
try {
// Structured output: the final answer itself follows the schema
const { output } = await generateText({
model: chatModel,
output: Output.object({ schema: jobSchema }),
prompt: `Extract the job details:\n\n${description}`,
});
return output; // typed as z.infer<typeof jobSchema>
} catch (error) {
if (NoObjectGeneratedError.isInstance(error)) {
// Parse or validation failed. error.text has the raw reply
console.error('Bad object', error.cause);
return null;
}
throw error;
}
}
Compare this with a tool. With a tool you would define searchJobs with an inputSchema, and the model would return arguments for your code to run. Using a tool only to get JSON back works, but it is a workaround from before structured output existed.
Tradeoffs
| Approach | Guarantee | Best for | Watch out for |
|---|---|---|---|
| JSON mode | Valid JSON syntax only | Older models without schema support | Missing or extra fields |
| Structured output | JSON that follows your schema | Forms, cards, extraction, UI data | Schema feature limits, first-call delay |
| Function calling | Typed arguments for your function | Actions and data lookups in your code | Extra round trip, security of the tool |
What Interviewers Actually Check
- Whether you can say exactly what JSON mode does not guarantee
- Whether you pick based on who consumes the output
- Whether you know strict schemas use nullable fields instead of optional ones
- Whether you still validate after strict output, and can explain why
- Whether you know your server, not the model, executes a tool
Follow-Up Questions
- Why does the first request with a new schema take longer?
- How would you handle a field that has a regex rule the provider does not support?
- What happens to your schema guarantee when the response hits the output token limit?
- Can you stream structured output to the UI? What does the client receive mid-stream?
- When would you combine a tool call and a structured final answer in one request?
Common Candidate Mistakes
- Calling JSON mode and structured output the same thing
- Using
.optional()everywhere and then hitting strict schema errors - Skipping validation because "strict mode guarantees it"
- Explaining function calling as "the model runs my function"
- Ignoring refusals, so the UI tries to render a refusal as a job card
Interview Readiness Checklist
Before you leave this question, make sure you can answer:
- Can you explain the guarantee of JSON mode, structured output and function calling in one line each?
- Can you choose between structured output and a tool for a given feature?
- Can you write a strict-friendly Zod schema?
- Can you name two cases where strict output still fails?
- Can you write
generateTextwithOutput.objectand handleNoObjectGeneratedError?
Summary
JSON mode gives you parseable JSON and nothing more. Structured output constrains the reply to your JSON Schema, which makes it the right default when your UI or database consumes the result. Function calling uses schemas for tool arguments, so the model can ask your code to do something before it answers. Strict schemas want every key present, so use nullable fields for missing data. Even with strict mode, refusals and token limits can break the shape, so validate the result in your code and handle the failure path.
If structured output enforces the schema, do I still need Zod on my side?
Yes. Rules like minimum, maximum or string length may be dropped from the schema the provider enforces, a refusal or a token limit can cut the output short, and older models may not support strict schemas at all. Validating the final object in your code is cheap insurance.
Is JSON mode still useful?
OpenAI describes Structured Outputs as the evolution of JSON mode and recommends it where supported. JSON mode is mostly a fallback for models that do not support schemas.
Can a single request use structured output and tools together?
Yes. Anthropic, for example, documents JSON outputs and strict tool use as features you can use separately or together. The tools control how the model calls your code, the output format controls its final answer.
Advertisement
Stay Updated
Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.
Advertisement