Strukturierte Ausgaben mit OpenAI-kompatiblen APIs: Leitfaden zu JSON Schema
Praxisleitfaden für strikte JSON-Schemas mit Responses und Chat Completions, einschließlich Validierung, Fehlerbehandlung und Routentests.

Structured Outputs ermöglichen JSON-Antworten, die einem definierten Schema folgen, statt ein Modell lediglich per Prompt um „JSON“ zu bitten. Bei einer OpenAI-kompatiblen API kann dasselbe JSON Schema über Responses oder Chat Completions verwendet werden. Die äußeren Anfragefelder unterscheiden sich jedoch, und Modell sowie Route müssen konkret geprüft werden.
Ein sicheres Produktionsmuster besteht aus drei Schichten: strict verwenden, wenn das Modell es unterstützt, das Ergebnis in der Anwendung erneut parsen und validieren und anschließend deterministische Geschäftsregeln anwenden. Schema-Konformität verhindert viele Formatfehler, beweist aber keine faktische oder semantische Richtigkeit.
Structured Outputs ist nicht dasselbe wie der JSON-Modus
| Methode | Gültiges JSON | Erzwingt das Schema | Typischer Einsatz |
|---|---|---|---|
| Nur Prompt | Nicht garantiert | Nein | Prototypen, die Analysefehler tolerieren |
| JSON-Modus | Bei Unterstützung und vollständiger Ausgabe | Nein | Flexibles JSON mit Validierung in der Anwendung |
Structured Outputs mit strict: true |
Mit Abschluss- und Ablehnungsbehandlung | Innerhalb des unterstützten Teilumfangs | Typisierte Extraktion und Arbeitsabläufe |
Der OpenAI-Leitfaden zu Structured Outputs empfiehlt diese Variante vor dem JSON-Modus, wenn Modell und Endpunkt sie unterstützen. Ein strukturiertes Antwortformat dient einer vorhersagbaren Datenantwort; Function Calling fordert dagegen eine Aktion der Anwendung an. Strikte Schemas können ähnlich sein, Aufruf-IDs und Ergebnisnachrichten gehören aber zu einem anderen Vertrag.
Das Schema vor dem Endpunkt definieren
Für die Triage eines Support-Tickets werden vier Felder benötigt:
{
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account"]
},
"priority": {
"type": "integer",
"minimum": 1,
"maximum": 3
},
"requires_human": {
"type": "boolean"
},
"summary": {
"type": "string"
}
},
"required": ["category", "priority", "requires_human", "summary"],
"additionalProperties": false
}
Pflichtfelder und additionalProperties: false schaffen ein stabiles Objekt. Sie machen jedoch nicht jedes JSON-Schema-Schlüsselwort portabel. OpenAI dokumentiert einen Teilumfang; andere OpenAI-kompatible Anbieter können einen anderen Teilumfang oder keinen strikten Schema-Modus unterstützen.
Das Schema mit der Responses API senden
Responses erwartet das Schema unter text.format:
export MODELFLARE_API_KEY="<YOUR_API_KEY>"
export MODEL_ID="<MODEL_WITH_VERIFIED_STRUCTURED_OUTPUT_SUPPORT>"
curl -sS https://modelflare.dev/v1/responses \
-H "Authorization: Bearer $MODELFLARE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$MODEL_ID\",
\"input\": \"Dem Kunden wurde der Betrag doppelt berechnet und er verlangt eine Erstattung.\",
\"text\": {
\"format\": {
\"type\": \"json_schema\",
\"name\": \"support_ticket\",
\"schema\": {
\"type\": \"object\",
\"properties\": {
\"category\": {
\"type\": \"string\",
\"enum\": [\"billing\", \"technical\", \"account\"]
},
\"priority\": {
\"type\": \"integer\",
\"minimum\": 1,
\"maximum\": 3
},
\"requires_human\": { \"type\": \"boolean\" },
\"summary\": { \"type\": \"string\" }
},
\"required\": [\"category\", \"priority\", \"requires_human\", \"summary\"],
\"additionalProperties\": false
},
\"strict\": true
}
}
}"
Die Anfrage geht mit Authorization: Bearer <YOUR_API_KEY> an POST https://modelflare.dev/v1/responses. Generierter Inhalt befindet sich in typisierten Ausgabeelementen. SDKs können Hilfsfunktionen für aggregierten Text oder bereits analysierte Ausgaben anbieten; ein HTTP-Client sollte den fertigen Text dennoch ausdrücklich finden und als JSON analysieren.
Dasselbe Schema mit Chat Completions senden
Chat Completions verwendet response_format.json_schema:
curl -sS https://modelflare.dev/v1/chat/completions \
-H "Authorization: Bearer $MODELFLARE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$MODEL_ID\",
\"messages\": [
{
\"role\": \"user\",
\"content\": \"Dem Kunden wurde der Betrag doppelt berechnet und er verlangt eine Erstattung.\"
}
],
\"response_format\": {
\"type\": \"json_schema\",
\"json_schema\": {
\"name\": \"support_ticket\",
\"schema\": {
\"type\": \"object\",
\"properties\": {
\"category\": {
\"type\": \"string\",
\"enum\": [\"billing\", \"technical\", \"account\"]
},
\"priority\": {
\"type\": \"integer\",
\"minimum\": 1,
\"maximum\": 3
},
\"requires_human\": { \"type\": \"boolean\" },
\"summary\": { \"type\": \"string\" }
},
\"required\": [\"category\", \"priority\", \"requires_human\", \"summary\"],
\"additionalProperties\": false
},
\"strict\": true
}
}
}"
Der JSON-Text liegt normalerweise in choices[0].message.content und muss geparst werden.
| Zweck | Responses API | Chat Completions |
|---|---|---|
| Schema-Container | text.format |
response_format.json_schema |
| Format-Typ | text.format.type |
response_format.type |
| Name | text.format.name |
response_format.json_schema.name |
| Schema | text.format.schema |
response_format.json_schema.schema |
| Strict | text.format.strict |
response_format.json_schema.strict |
| Ergebnis | Typisierte Ausgabeelemente / Hilfsfunktion | choices[0].message.content |
Modelflare konvertiert beide Hüllen auf unterstützten OpenAI/Codex-Routen. Diese Konvertierung erzeugt aber keine Structured-Outputs-Unterstützung in einem Upstream-Modell, das die Funktion nicht besitzt. Bei unverändert durchgereichten Chat Completions bleibt der Anbietervertrag maßgeblich.
Struktur und Bedeutung getrennt validieren
{
"category": "billing",
"priority": 2,
"requires_human": true,
"summary": "Der Kunde meldet eine Doppelabbuchung und verlangt eine Erstattung."
}
Strukturelle Validierung
Ein JSON-Schema-Validator prüft Pflichtfelder, unerwartete Eigenschaften, Typen, Aufzählungswerte und Wertebereiche. Auch bei zugesicherter strikter Einhaltung schützt die Validierung vor inkompatiblen Routen, Integrationsfehlern, abgeschnittenen Ausgaben und späteren Vertragsänderungen.
Semantische und geschäftliche Validierung
Das Schema weiß nicht, ob eine Doppelabbuchung wirklich stattgefunden hat, ob priority: 2 korrekt ist oder wer eine Erstattung genehmigen darf. Das Modellobjekt ist ein Vorschlag, der mit autoritativen Daten verglichen werden muss. Berechtigungen, Finanzlimits und Sicherheitsregeln bleiben in deterministischem Code. Ein strukturell gültiges Objekt darf keine solche Grenze umgehen.
Unvollständige und außergewöhnliche Ausgaben behandeln
Ablehnungen
Status und Ablehnungsdarstellung müssen vor der JSON-Analyse geprüft werden. Eine Sicherheitsablehnung ist kein Analysefehler.
Abgeschnittene Ausgaben und Ausgabelimits
Endet die Generierung vor dem Objektabschluss, kann das Schema die fehlenden Zeichen nicht rekonstruieren. Abschlussstatus und Stoppgrund prüfen und ein ausreichend großes, aber begrenztes Ausgabelimit setzen.
Nicht unterstützte Schema-Keywords
Mit Objekten, Arrays, primitiven Typen, Aufzählungen, Pflichtfeldern und ausdrücklichen Regeln für zusätzliche Eigenschaften beginnen. Referenzen, rekursive Strukturen, komplexe Vereinigungen und erweiterte Validatoren erst nach Prüfung der aktuellen Anbieterdokumentation einsetzen.
Latenz beim ersten Schema
Ein neuer Schema-Entwurf kann serverseitig vorverarbeitet und zwischengespeichert werden. Stabile, versionierte Schemas wiederverwenden und die erste Nutzung getrennt vom stabilen Betrieb messen.
Inkompatibles Modell oder inkompatible Route
Ein Endpunkt kann normale Chat Completions akzeptieren, aber json_schema ablehnen oder strict ignorieren. Ein 200 mit JSON beweist keine strikte Einhaltung. Ungültige Eingaben und Grenzfälle gehören zum Test.
Vor Produktion eine Kompatibilitätsmatrix ausführen
| Test | Aufzuzeichnende Evidenz |
|---|---|
| Minimales Pflichtobjekt | Status, Modell, Route, analysiertes Objekt, Validierung |
| Jeder Aufzählungswert | Erzeugung und Analyse aller erlaubten Werte |
| Fehlende Information | Begrenzter Ersatzwert oder Rückfrage |
| Sicherheitssensitiver Input | Ablehnungsdarstellung und Anwendungsbehandlung |
| Niedriges Ausgabelimit | Abschlussstatus und Behandlung abgeschnittener Ausgaben |
| Nicht unterstütztes Feature | Expliziter Fehler oder stilles Ignorieren |
| Responses- und Chat-Wrapper | Gleichwertige Anwendungsobjekte |
| Wiederholtes stabiles Schema | Erste Nutzung gegenüber stabilem Betrieb |
Schema, Prompt, Region, Streaming-Modus und Ausgabelimit müssen bei Vergleichen konstant bleiben. Da sich Anbieterverhalten und Modelle ändern, gehört das Testdatum zum Nachweis.
Den Endpunkt nach dem Arbeitsablauftest wählen
Responses passt zu typisierten Ausgabeelementen, Responses-Streaming oder einem größeren Werkzeugablauf. Chat Completions passt zu einer stabilen nachrichtenbasierten Integration, wenn response_format auf der konkreten Route unterstützt wird. Siehe Responses API vs. Chat Completions.
Unabhängig vom Endpunkt:
- eine versionierte maßgebliche Quelle für JSON Schema behalten;
- nur die Hülle, nicht die Bedeutung ändern;
- die vollständige Antwort validieren;
- danach deterministische Geschäftsregeln anwenden;
- Analyse-, Ablehnungs-, Abschneide- und Kompatibilitätsfehler getrennt überwachen.
Für die Migration dient der Leitfaden zu OpenAI-kompatiblen APIs, für unvollständige Datenströme der Leitfaden zum Streaming von KI-APIs. Unter Modelle und Preise das aktuelle Angebot prüfen und Structured Outputs auf genau der Route testen, die der API-Schlüssel verwendet.
Structured Outputs machen eine Modellantwort zu einer verlässlicheren Anwendungsschnittstelle. Sie ersetzen keine Faktenprüfung, Autorisierung oder Abrechnungslogik. „OpenAI-kompatibel“ bleibt eine für jede Funktion zu prüfende Aussage.