Skip to content
Go back

When to Use Structured Output (JSON Mode) in LLMs

By SumGuy 5 min read
When to Use Structured Output (JSON Mode) in LLMs

The Appeal: Guaranteed JSON

Structured output (JSON mode) promises: “The model will always output valid JSON, never unstructured text.”

Sounds great. But there’s a catch: forcing structure sometimes makes the model dumber.

How JSON Mode Works

Most LLM APIs let you specify output format:

import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
response_format={"type": "json_object"},
messages=[
{"role": "user", "content": "Extract names and ages from: 'Alice is 30, Bob is 25'"}
]
)
# Response is guaranteed valid JSON
result = json.loads(message.content[0].text)

Ollama also supports this:

Terminal window
curl http://localhost:11434/api/generate -d '{
"model": "mistral",
"prompt": "Extract JSON: {\"name\": \"...\", \"age\": ...} from: Alice is 30",
"format": "json",
"stream": false
}'

The model’s output will be valid JSON, not “name: Alice, age: 30” or other variations.

When JSON Mode Saves You

Use JSON mode when:

  1. Extraction from unstructured text

    • “Pull names, emails, dates from this doc”
    • Model knows exactly what to extract
  2. Form filling / structured categorization

    • “Assign sentiment: positive/negative/neutral”
    • “Extract: name, email, phone from this resume”
  3. Data pipeline integrations

    • You can’t afford parsing errors
    • JSON→database is standard
# Example: Extract structured data from free text
prompt = """
Extract the following fields from this support ticket:
- issue: What's the problem?
- priority: critical/high/medium/low
- component: backend/frontend/database/infrastructure
- action_required: A brief next step
Ticket: "The login page is broken. Users can't sign in. This is blocking our launch."
"""
# With JSON mode, you get valid JSON guaranteed
# Without it, you might get: "issue: The login page is broken\npriority: critical"

When JSON Mode Hurts

JSON mode constraints the model’s reasoning. Some models perform worse when forced into JSON.

Consider:

User: "Explain why OAuth is better than basic auth"
With JSON mode:
- Model is constrained to structure
- May oversimplify to fit the schema
- Loses nuance
Without JSON mode:
- Model can write naturally, include caveats
- Can say "it depends" with explanation

Real example:

Terminal window
# Without JSON mode
$ curl http://localhost:11434/api/generate -d '{
"model": "mistral",
"prompt": "What are the tradeoffs of microservices?",
"stream": false
}'
# Output: "Microservices offer scalability and independence, but they add complexity..."
# (Clear, nuanced, well-reasoned)
# With JSON mode
curl http://localhost:11434/api/generate -d '{
"model": "mistral",
"prompt": "What are the tradeoffs of microservices? Output as JSON: {\"pros\": [...], \"cons\": [...]}",
"format": "json",
"stream": false
}'
# Output: {"pros": ["Scalability", "Independence"], "cons": ["Complexity", "Cost"]}
# (Oversimplified, loses explanation)

Decision Tree

Use JSON mode if:

Skip JSON mode if:

Hybrid Approach: JSON + Explanation

Get the best of both worlds:

prompt = """
Analyze this code for security issues. Output as JSON:
{
"vulnerability": "name of issue",
"severity": "critical/high/medium/low",
"explanation": "why this is a problem",
"fix": "how to fix it"
}
Code:
```python
import os
password = os.getenv("DB_PASSWORD") # Hardcoded in logs

"""

Model can explain fully within the “explanation” field

while still outputting valid JSON

This works because JSON allows text fields. The model can be verbose and nuanced, but the output is still machine-parseable.
## Testing: Before and After
Always benchmark JSON mode vs. free form:
```bash
#!/bin/bash
# Test both modes on the same prompt
prompt="Extract: name, email, age from 'John Doe (john@example.com) is 35 years old'"
echo "=== Without JSON mode ==="
curl -s http://localhost:11434/api/generate -d "{
\"model\": \"mistral\",
\"prompt\": \"$prompt\",
\"stream\": false
}" | jq '.response'
echo ""
echo "=== With JSON mode ==="
curl -s http://localhost:11434/api/generate -d "{
\"model\": \"mistral\",
\"prompt\": \"$prompt\nOutput as valid JSON: {\\\"name\\\": ..., \\\"email\\\": ..., \\\"age\\\": ...}\",
\"format\": \"json\",
\"stream\": false
}" | jq '.response'
# Compare:
# - Which is easier to parse?
# - Which is more accurate?
# - Does quality differ?

The Real Cost

JSON mode adds computational overhead. The model has to track syntax, ensure quotes match, etc. This makes inference slightly slower and can degrade quality on complex reasoning tasks.

For simple extraction? The overhead is negligible and the safety gain is huge.

For “explain this concept”? You’re paying a real penalty for no benefit.

Bottom Line

JSON mode is a power tool for extraction and data pipelines. Use it there. Don’t use it for explanation, analysis, or anything where nuance matters.

When in doubt, let the model write freely, then parse the output with a simple regex or JSON.loads(). Your model will thank you with better output.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it may appear here.


Previous Post
AMD Lemonade: Local LLM Serving for AMD GPUs
Next Post
Browser GPU Acceleration on Linux in 2026

Related Posts