このページはまだ日本語に翻訳されていません。英語の原文を表示します。
Structured outputs
Pinning the response shape with a JSON schema
response_format lets you ask a model to return JSON that matches a schema you define, instead of free-form text. This is worth reaching for whenever your code parses the reply — it removes an entire class of "the model wrapped it in markdown" or "it invented an extra field" bugs.
Using it
Set type to json_schema and give the schema a name:
{
"model": "google/gemma-4-26b-a4b",
"messages": [
{ "role": "user", "content": "Extract the city and temperature: it's 21°C in Busan today." }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "weather",
"strict": true,
"schema": {
"type": "object",
"properties": {
"city": { "type": "string" },
"temperature_c": { "type": "number" }
},
"required": ["city", "temperature_c"],
"additionalProperties": false
}
}
}
}The reply's message.content is a JSON string matching the schema:
{ "city": "Busan", "temperature_c": 21 }It is still a string — JSON.parse it yourself. We do not decode it for you, because doing so would silently swallow the case where the model produced invalid JSON.
Model support
Both of our catalog models list response_format in supported_parameters:
curl -s "https://openrouter.myip.co.kr/api/v1/models" | jq '.data[] | {id, supported_parameters}'Sending response_format to a model whose supported_parameters does not include it is not blocked here — the serving engine decides whether to honour it, ignore it, or error. To have unsupported candidates filtered out of the chain instead of silently answering with plain text, set provider.require_parameters: true (see Provider routing).
Streaming
response_format works the same way with stream: true. The model streams the JSON text token by token in delta.content; concatenate the deltas and parse once finish_reason arrives, the same as you would for any streamed text. See Streaming.
let json = '';
for await (const chunk of stream) {
json += chunk.choices[0]?.delta?.content ?? '';
}
const data = JSON.parse(json);Do not try to JSON.parse a partial buffer on every chunk — it is not valid JSON until the stream ends.
A full example
curl https://openrouter.myip.co.kr/api/v1/chat/completions \
-H "Authorization: Bearer $MYIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-26b-a4b",
"messages": [
{"role": "user", "content": "Extract the city and temperature: it'\''s 21°C in Busan today."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "weather",
"strict": true,
"schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"temperature_c": {"type": "number"}
},
"required": ["city", "temperature_c"],
"additionalProperties": false
}
}
}
}'Best practices
- Write descriptions into the schema.
"description": "ISO 4217 currency code"on a property guides the model more than the field name alone. - Use
strict: truewhenever the engine you are calling supports it, and treat conformance as "usually" rather than "always" until you have tested that specific model. - Keep schemas flat where you can. Deep nesting and unusual JSON Schema features (
oneOf,$ref) are more likely to be only partially supported by a given engine's strict mode. - Validate anyway. Parse the string, then validate it against your schema in your own code (e.g. with
ajvorzod) before trusting it.response_formatreduces malformed output; it does not eliminate the need to handle it.
Errors
| Situation | What happens |
|---|---|
Model does not support response_format | Engine-dependent — usually the field is ignored and you get plain text back, not an error |
json_schema is not valid JSON Schema | The upstream call fails; surfaces as 502 provider_error with the upstream's message in metadata |
Model returns text that does not match the schema despite strict: true | Not caught by us — validate the parsed object yourself |
See Errors and debugging for the general error envelope.
最終更新 2026/09/05