Structured output (JSON mode)
Get JSON from models on BigModel.io with response_format where the group passes it through, or a tool schema where response_format is dropped, then validate it.
On this page
There are two ways to get machine-readable JSON: the OpenAI response_format field, or a tool whose parameters are your schema. Which one works depends on your key's group.
| Key's group | response_format |
Tool schema |
|---|---|---|
| GLM, DeepSeek (Chat Completions only) | Passed to the model unchanged; works if the model supports it | Works if the model supports tools |
Anthropic-platform groups, on /v1/chat/completions |
Dropped | Works |
| Groups where Chat Completions is converted to Responses | Dropped, together with n, seed, user and logprobs |
Works |
When response_format is dropped there is no error. The request succeeds, but the model is not constrained, so you may get prose or JSON in a Markdown fence. Always validate the output.
#Which kind of group do I have?
Send any request to /v1/messages with your key. A 404 that says the platform only supports /v1/chat/completions means a Chat Completions only group, where response_format passes through. Any other answer means it may be dropped, so use the tool schema option.
#Option 1: response_format
On Chat Completions only groups, use json_schema if the model supports it, or json_object. Also ask for JSON in the prompt; some models require it.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://bigmodel.io/v1", api_key=os.environ["BIGMODEL_API_KEY"])
completion = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "system", "content": "Reply with a JSON object with keys name and year."},
{"role": "user", "content": "Which language did Guido van Rossum create?"},
],
response_format={"type": "json_object"},
)
data = json.loads(completion.choices[0].message.content)
print(data["name"], data["year"])import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://bigmodel.io/v1", apiKey: process.env.BIGMODEL_API_KEY });
const completion = await client.chat.completions.create({
model: "deepseek-v4-flash",
messages: [
{ role: "system", content: "Reply with a JSON object with keys name and year." },
{ role: "user", content: "Which language did Guido van Rossum create?" },
],
response_format: { type: "json_object" },
});
console.log(JSON.parse(completion.choices[0].message.content));curl https://bigmodel.io/v1/chat/completions \
-H "Authorization: Bearer $BIGMODEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [
{"role": "system", "content": "Reply with a JSON object with keys name and year."},
{"role": "user", "content": "Which language did Guido van Rossum create?"}
],
"response_format": {"type": "json_object"}
}'Support differs per model: some accept json_object but not json_schema, and strict schema enforcement is not universal. Check the model vendor's documentation for the model you choose.
#Option 2: a tool schema (works on every group)
tools and tool_choice survive every conversion, so a forced tool call is the portable way to get schema-shaped JSON.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://bigmodel.io/v1", api_key=os.environ["BIGMODEL_API_KEY"])
schema = {
"type": "object",
"properties": {"name": {"type": "string"}, "year": {"type": "integer"}},
"required": ["name", "year"],
}
completion = client.chat.completions.create(
model="glm-5.3",
messages=[{"role": "user", "content": "Which language did Guido van Rossum create?"}],
tools=[{"type": "function", "function": {"name": "answer", "description": "Return the answer", "parameters": schema}}],
tool_choice={"type": "function", "function": {"name": "answer"}},
)
data = json.loads(completion.choices[0].message.tool_calls[0].function.arguments)
print(data)const schema = {
type: "object",
properties: { name: { type: "string" }, year: { type: "integer" } },
required: ["name", "year"],
};
const completion = await client.chat.completions.create({
model: "glm-5.3",
messages: [{ role: "user", content: "Which language did Guido van Rossum create?" }],
tools: [{ type: "function", function: { name: "answer", description: "Return the answer", parameters: schema } }],
tool_choice: { type: "function", function: { name: "answer" } },
});
console.log(JSON.parse(completion.choices[0].message.tool_calls[0].function.arguments));If a model does not accept a forced function, use "tool_choice": "required" or "auto" with a clear instruction.
#Validate the result
Neither option guarantees valid data from every model. Parse and validate, and retry once on failure:
from pydantic import BaseModel, ValidationError
class Answer(BaseModel):
name: str
year: int
try:
answer = Answer.model_validate_json(raw_json)
except ValidationError as err:
# send err back to the model and ask it to fix the JSON, or retry
raise#Verify the setup
Run the cURL example. choices[0].message.content should be a JSON object such as {"name": "Python", "year": 1991}, with no surrounding text. If you get prose, response_format was dropped or is not supported by the model; switch to the tool schema.
#Troubleshooting
The reply is prose, or JSON inside a Markdown code fence. response_format was dropped on your group or ignored by the model. Use the tool schema option, or strip the fence before parsing.
400 from the provider about response_format. The model does not support the format you sent, often json_schema. Use json_object, or the tool schema option.
The JSON is cut off. The reply hit max_tokens; finish_reason is length. Raise max_tokens or ask for a smaller object.
seed, n or logprobs seem to have no effect. On converted groups these fields are dropped along with response_format. Only Chat Completions only groups pass them through, and then only if the model supports them.
503 api_error "No available accounts". The model is not served to your key's group. See Model IDs.
#Related
- Tool calling for the full tool loop.
- Chat Completions API reference.
- Errors.
Updated · View as Markdown