OpenAI’s JSON Mode is a feature that forces the model to output valid JSON.
Here’s how it looks in practice:
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant designed to output JSON. Only output JSON."},
{"role": "user", "content": "Give me a JSON object with a list of fruits and their colors."}
],
response_format={ "type": "json_object" }
)
print(completion.choices[0].message.content)
This will produce output like:
{
"fruits": [
{"name": "apple", "color": "red"},
{"name": "banana", "color": "yellow"},
{"name": "grape", "color": "purple"}
]
}
The core problem this solves is the unreliability of getting structured data from LLMs. Before JSON Mode, you’d often get text that looked like JSON but was malformed, requiring robust error handling and parsing on your end. This meant spending time cleaning up outputs, writing regex, or using libraries that try to salvage broken JSON.
Internally, when you enable response_format={ "type": "json_object" }, OpenAI’s system doesn’t just append "output valid JSON" to the prompt. It fundamentally changes how the model generates tokens. The model’s output layer is constrained to only produce tokens that can form a syntactically correct JSON structure. This is a much more robust guarantee than simply instructing the model to behave.
The key levers you control are:
model: While many models support JSON Mode, newer, more capable models likegpt-4oandgpt-4-turbowill generally perform better and adhere more strictly to the format. Older models might still occasionally produce malformed output, even with the setting.response_format={ "type": "json_object" }: This is the switch that turns on the JSON Mode. It’s a parameter passed in the API call.- System Prompt: While JSON Mode enforces the syntax, your system prompt is still crucial for defining the content and structure of the JSON. You tell the model what JSON to generate. For example, you can specify field names, data types, and nesting.
When you use JSON Mode, the model is essentially working within a more rigid grammar. It knows that after an opening brace {, the next token must be a key (a string in double quotes), followed by a colon :, then a value (which could be another object, an array, a string, number, boolean, or null). This tight control significantly reduces the chance of syntax errors.
What most people don’t realize is that even with JSON Mode, the semantic correctness of the JSON still depends entirely on the model’s understanding of your prompt and its ability to reason about the requested data. If you ask for a list of "fruits and their colors" and the model hallucinates a fruit or assigns a nonsensical color, JSON Mode will happily wrap that incorrect information in valid JSON. The mode guarantees form, not necessarily truth.
The next problem you’ll likely encounter is handling the semantic correctness and validation of the JSON data after it’s generated.