Guides
JSON output
Ask for a JSON object, and the reply's content is JSON your code can parse. Describe the object you want in the messages, then check what comes back.
Ask for a JSON object
Set response_format to {"type": "json_object"}, and say in the messages that you want JSON and what it should look like:
curl https://acacus.ly/v1/chat/completions \
-H "Authorization: Bearer $ACACUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [
{"role": "system", "content": "Reply with a JSON object like {\"city\": \"...\", \"country\": \"...\"}."},
{"role": "user", "content": "What is the capital of Libya?"}
],
"response_format": {"type": "json_object"},
"thinking": {"type": "disabled"}
}'The reply to the curl example:
{
"id": "b4521a5d-a9be-476d-b27d-cb2c5213d70b",
"object": "chat.completion",
"created": 1790380578,
"model": "deepseek-flash",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"city\": \"Tripoli\", \"country\": \"Libya\"}"
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 51,
"completion_tokens": 14,
"total_tokens": 65,
"prompt_tokens_details": {
"cached_tokens": 0
},
"prompt_cache_hit_tokens": 0,
"prompt_cache_miss_tokens": 51
},
"system_fingerprint": "aeb56401ca74e127821c4f9126dcb669"
}message.content is a string that holds the JSON object. Parse it, as the Python and Node.js examples do. They printed Tripoli is the capital of Libya.
Describe the JSON in your messages
response_format alone doesn't tell the model which keys to use. DeepSeek's documentation asks you to use the word “json” in the system or user message, and to give an example of the object you want. Without an instruction to write JSON, it warns, the model may write only whitespace until it reaches max_tokens, and the request looks stuck.
Check the reply
JSON mode gives you JSON, not necessarily the keys and types you asked for. Before you use the object:
- Check
finish_reason.lengthmeans the reply reachedmax_tokensand the JSON is cut off. Raisemax_tokens, or ask for less. Free requests stop at 2,048 output tokens. - Check that
contentisn't empty. DeepSeek's documentation says JSON mode can occasionally return empty content, and that changing the prompt can help. - Check the keys and types against what you expect.
A schema library makes the last check short. This example uses Pydantic in Python and zod in Node.js:
# pip install openai (pydantic comes with it)
import os
from openai import OpenAI
from pydantic import BaseModel, ValidationError
client = OpenAI(
api_key=os.environ["ACACUS_API_KEY"],
base_url="https://acacus.ly/v1",
)
class Order(BaseModel):
item: str
quantity: int
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{
"role": "system",
"content": "Extract the order from the message. Reply with a JSON object "
"with these keys: item (string), quantity (integer).",
},
{"role": "user", "content": "Please send three bottles of water to the office."},
],
response_format={"type": "json_object"},
extra_body={"thinking": {"type": "disabled"}},
)
try:
order = Order.model_validate_json(response.choices[0].message.content or "")
except ValidationError as error:
raise SystemExit(f"The reply did not match: {error}")
print(order)The Python version printed:
item='water' quantity=3JSON schemas are not supported
DeepSeek refuses response_format with the type json_schema, which OpenAI uses for structured outputs. The request gets DeepSeek's 400 error, and nothing is charged:
{
"error": {
"message": "This response_format type is unavailable now (request_id: 275deb5d-4888-484a-9c89-55e12adab7ef)",
"type": "invalid_request_error",
"param": null,
"code": "invalid_request_error"
}
}So library helpers that send a JSON schema fail the same way, for example client.chat.completions.parse() with a Pydantic model in the OpenAI Python library. In LangChain, with_structured_output works with method="function_calling", which uses a tool instead. You have two ways to get an object of a fixed shape: ask for json_object and check the reply, as above, or use a tool, as below.
Use a tool as the schema
Describe the object as the parameters of a function, and force the model to call it with tool_choice. The arguments of the call are your object, as a JSON string. See Tool calling for how tools work.
# pip install openai
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ACACUS_API_KEY"],
base_url="https://acacus.ly/v1",
)
record_order = {
"type": "function",
"function": {
"name": "record_order",
"description": "Record the order in the message.",
"parameters": {
"type": "object",
"properties": {
"item": {"type": "string"},
"quantity": {"type": "integer"},
},
"required": ["item", "quantity"],
},
},
}
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Please send three bottles of water to the office."}],
tools=[record_order],
tool_choice={"type": "function", "function": {"name": "record_order"}},
extra_body={"thinking": {"type": "disabled"}},
)
arguments = response.choices[0].message.tool_calls[0].function.arguments
order = json.loads(arguments) # check it before you use it
print(order)The Python version printed:
{'item': 'water', 'quantity': 3}tool_choice.