Getting reliable structured data from models depends on how each vendor implements output constraints. This post compares json mode support llm providers across ten APIs so you can pick the right one for production extraction pipelines. We focus on what breaks in practice, not marketing sheets.
How each provider constrains JSON
OpenAI
OpenAI ships two mechanisms: response_format={"type":"json_object"} for loose JSON, and Structured Outputs with a JSON schema for strict adherence. Streaming works with both. The strict mode guarantees the schema, but only supports a subset of JSON Schema (no minLength, pattern, or free-form additionalProperties). Nested depth caps at 100 levels.
from openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-4o-mini",
response_format={
"type": "json_schema",
"json_schema": {"name":"pres","schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}
},
messages=[{"role":"user","content":"Return the president's name."}]
)
Anthropic
Claude has no native json mode. You force structure via tool use: define a single tool and force tool_choice. This yields valid JSON matching the tool input schema, but adds tool-call wrapping. Schema support mirrors OpenAI’s strict subset. Streaming returns the tool input as delta events.
import anthropic
c = anthropic.Anthropic()
c.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=256,
tools=[{"name":"emit","input_schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}],
tool_choice={"type":"tool","name":"emit"},
messages=[{"role":"user","content":"President name?"}]
)
Google Gemini
Gemini supports response_mime_type="application/json" and optionally response_schema. It enforces the schema loosely; complex nested arrays can drift. Streaming returns chunks of raw JSON text. It rejects schemas containing null union types.
import google.generativeai as genai
genai.configure(api_key="x")
m = genai.GenerativeModel("gemini-1.5-flash",
generation_config={"response_mime_type":"application/json",
"response_schema":{"type":"object","properties":{"name":{"type":"string"}}}})
m.generate_content("Give me the president's name")
Mistral
La Plateforme exposes response_format={"type":"json_object"}. No strict schema enforcement; it just guarantees parseable JSON. Good enough for lightweight ETL. Max output tokens still apply; truncate and you get cut JSON.
Cohere
Command R+ uses response_format={"type":"json_object"} via the chat API. Best-effort like Mistral. Tool use is more reliable for shape but still not schema-guaranteed. Latency is competitive in EU regions.
Groq
Groq serves open-weight models (Llama 3, Mixtral) with an OpenAI-compatible response_format flag. Because the underlying weights aren’t fine-tuned for strict JSON, you get best-effort parsing; speed is unmatched (sub-100ms TTFT on 8B models). No schema validation server-side.
Together AI
Together provides response_format={"type":"json_object"} on hosted Llama 3 and Qwen. Also supports Structured Outputs on some models via guidance. Throughput is high, but queueing happens under load. Their strict mode is model-dependent.
Fireworks AI
Fireworks mirrors OpenAI’s flag and adds function-calling for schema. Their fine-tuned firefunction models honor JSON tightly. Regular base models are best-effort.
Perplexity
Sonar models accept response_format=json on the OpenAI-compatible endpoint, but the online search wrapper often injects prose before the JSON. Not recommended for strict pipelines unless you post-filter.
Replicate
Replicate runs model containers (Llama, Mixtral) where you pass schema as a prompt adapter. No API-level JSON mode; you wrap with jsonformer or similar. Most manual, but most flexible for custom weights.
Comparison table
| Provider | Strict schema | Streaming | Cost model | Latency profile | Ecosystem notes |
|---|---|---|---|---|---|
| OpenAI | Yes (subset) | Yes | Per-token, no premium | Moderate | Largest model choice |
| Anthropic | Via tools | Yes | Per-token | Moderate | Long context |
| Gemini | Partial | Yes | Per-token, tiered | Low-mid | Multimodal |
| Mistral | No | Yes | Per-token | Low | European hosting |
| Cohere | No | Yes | Per-token | Low-mid | RAG-tuned |
| Groq | No | Yes | Per-token, cheap | Very low | Open weights |
| Together | Partial | Yes | Per-token | Mid | Many open models |
| Fireworks | Partial | Yes | Per-token | Low | Function models |
| Perplexity | No | Yes | Per-token + search | Mid | Web search |
| Replicate | No | Manual | Per-second | Variable | Custom containers |
Dimensions that actually matter
Capabilities: strict vs best-effort
If you need guaranteed keys, OpenAI Structured Outputs or Anthropic tool-force are the only battle-tested options. The rest will occasionally drop a field. For json mode support llm providers, the strict subset excludes minLength, pattern, and additionalProperties freedom. Strict modes also forbid recursive schemas.
Cost model
Nobody charges extra for JSON mode itself. You pay base token rates. Groq and Together are cheapest for high volume open-weight inference. OpenAI and Anthropic sit at the top of the price band but offer reliability. If you meter per token through a gateway, expect the same underlying cost plus possible margin.
Latency and throughput
Groq wins on time-to-first-token. OpenAI and Gemini are consistent. Replicate depends on cold starts. If you stream JSON, parse incrementally with a tolerant parser like ijson to avoid blocking. Best-effort providers may emit a trailing comma under load; validate with json.loads after stripping.
Ergonomics
OpenAI’s SDK is the reference. Anthropic’s tool wrapping is verbose. Gemini’s mime type is clean. Mistral and Cohere copy OpenAI’s shape. A gateway such as n4n.ai exposes one OpenAI-compatible endpoint across 240+ models and forwards provider cache-control hints, letting you swap json mode support llm providers without client changes. That removes the need to maintain separate Anthropic tool boilerplate.
Ecosystem and model coverage
OpenAI and Azure give you the most managed models. Groq/Together/Fireworks give you Llama 3 variants. If you need a specific fine-tune, Replicate likely hosts it. Gemini adds native vision if your extraction needs images.
Limits and edge cases
Strict schemas limit recursion depth (OpenAI caps at 100 nested levels). Streaming JSON can emit incomplete fragments; always validate post-stream. Gemini rejects schemas with null types. Mistral truncates if max_tokens too low. Cohere’s JSON mode fails silently on very large objects. Replicate requires you to catch container OOMs.
Implementation pattern for resilient parsing
When calling best-effort endpoints, wrap the response:
import json
def safe_parse(streamed_text):
try:
return json.loads(streamed_text)
except json.JSONDecodeError:
# attempt to close trailing structures (naive demo)
fixed = streamed_text.rstrip().rstrip(',') + '}'
return json.loads(fixed)
This shows the tolerance layer you need for non-strict providers. Production code should use a proper incremental parser.
Which to choose
Strict compliance extraction
Use OpenAI Structured Outputs or Anthropic forced tool use. You get schema guarantees and streaming. Pay the token premium. This is the only safe path for financial or legal records.
Low-latency best-effort
Groq with Llama 3.1-8B and response_format gives sub-100ms parses for simple objects. Validate downstream. Good for UI autocomplete.
Multi-model routing with fallback
If you want to issue the same JSON request to multiple backends, standardize on the OpenAI flag and route through a compatible gateway. That avoids rewriting Anthropic tool boilerplate per call and gives automatic fallback when a provider is degraded.
Open-weight and self-host adjacent
Together, Fireworks, or Replicate. Expect to add a validation layer; none enforce strict schema natively except Fireworks function models. Use when data residency or cost dominates.
Search-augmented JSON
Perplexity only if you need web data inside the object; otherwise its prose leakage breaks parsers.
JSON mode support llm providers is fragmented. Pick strict where money is on the line, best-effort where speed wins, and route through a uniform interface to keep your client code honest.