Get Reliable JSON from a Local Model: Ollama Structured Outputs Explained
Note: Some future links on this site may be affiliate links. We never claim hands-on testing; guides are researched from the public sources listed in each article.
How we wrote this: A summary of Ollama's official structured outputs documentation (linked below), checked October 29, 2026. The examples follow the docs; model names are examples only.
A chat answer is fine for a person. A script needs something it can parse: a list of names, an invoice total, a yes/no flag. Asking a model nicely to "reply in JSON" works most of the time, which isn't good enough for automation. Ollama's structured outputs feature lets you hand the model a JSON schema and have its reply follow it.
Two levels: any JSON, or JSON that fits a schema
Both use the format field of Ollama's local API (see our Ollama API basics guide if you haven't called it before).
Any valid JSON: set "format": "json".
curl -X POST http://localhost:11434/api/chat -H "Content-Type: application/json" -d '{
"model": "gpt-oss",
"messages": [{"role": "user", "content": "Tell me about Canada in one line"}],
"stream": false,
"format": "json"
}'
JSON that matches a schema: put a JSON schema in format instead. This is the example from the structured outputs docs:
"format": {
"type": "object",
"properties": {
"name": {"type": "string"},
"capital": {"type": "string"},
"languages": {"type": "array", "items": {"type": "string"}}
},
"required": ["name", "capital", "languages"]
}
The reply's message.content is then a JSON string with those fields.
In Python, with Pydantic
The docs recommend defining the shape once with Pydantic, passing its schema to format, then validating the reply:
from ollama import chat
from pydantic import BaseModel
class Country(BaseModel):
name: str
capital: str
languages: list[str]
response = chat(
model='gpt-oss',
messages=[{'role': 'user', 'content': 'Tell me about Canada.'}],
format=Country.model_json_schema(),
)
country = Country.model_validate_json(response.message.content)
In JavaScript, with Zod
The same idea, using z.toJSONSchema() to turn a Zod schema into the format value and Country.parse(...) to check the result. The docs show the full example.
Practical uses
The docs give two patterns that map well to everyday office work:
- Extracting data from text. Their example pulls a list of pets (name, animal, age, color) out of a paragraph. The same shape works for pulling names, dates and amounts out of emails or notes, all on your own machine.
- Describing images. Vision models accept the same
formatparameter. The docs' example returns a summary, a list of detected objects, the scene, colors, and a time of day chosen from a fixed list.
Because everything runs locally, the documents never leave your computer. See chat with your documents locally for the bigger picture.
Tips from the docs for dependable results
- Also put the schema in the prompt. The docs say it is "ideal to also pass the JSON schema as a string in the prompt to ground the model's response."
- Lower the temperature, for example to 0, for more consistent output.
- Validate every reply with the same Pydantic or Zod schema you sent, and decide what your script does if validation fails.
- OpenAI-style clients work too. The docs note structured outputs are available through Ollama's OpenAI-compatible API using
response_format. - Local only, for now. The docs note that Ollama's cloud doesn't currently support structured outputs.
A schema controls the shape of the answer. It says nothing about whether the facts in it are right. For anything that matters (money, dates, names), keep a person checking the results or compare them against the source.