← Journal

    Werkbank

    Strukturierte Outputs: JSON von LLMs zuverlässig erzwingen

    Haris Muranović · 03. Juni 2025 · 7 Min.

    Wer ein Sprachmodell in eine Software integriert, braucht selten Prosa. Die Anwendung erwartet Daten: extrahierte Felder aus einem Dokument, eine Klassifikation mit Begründung, eine Liste von Aufgaben mit Fälligkeit. Strukturierte Outputs sind die Brücke zwischen dem, was ein Modell gut kann, und dem, was Code verarbeiten kann. Und genau an dieser Brücke scheitern erstaunlich viele Integrationen.

    Das typische Fehlerbild kennt jeder, der es einmal probiert hat: Das Modell liefert fast immer sauberes JSON, aber eben nur fast. Mal steht ein erklärender Satz vor der Struktur, mal fehlt ein Pflichtfeld, mal erfindet das Modell einen Feldnamen, der im Schema nie vorkam. In der Demo fällt das nicht auf. In Produktion, bei tausenden Anfragen pro Tag, wird aus dem seltenen Ausreißer ein täglicher Vorfall. Die Lösung ist kein besserer Prompt, sondern eine Architektur, die mit Abweichungen rechnet.

    JSON-Mode und Schema-Erzwingung: zwei Stufen der Verbindlichkeit

    Die meisten Modellanbieter bieten heute zwei Mechanismen an, die oft verwechselt werden. Der klassische JSON-Mode garantiert lediglich, dass die Ausgabe syntaktisch gültiges JSON ist. Das ist besser als nichts, aber es sagt nichts über den Inhalt: Feldnamen, Typen und Pflichtfelder bleiben dem Modell überlassen. Ein syntaktisch perfektes Objekt mit den falschen Feldern ist für die Anwendung genauso wertlos wie Fließtext.

    Die zweite Stufe ist die Schema-Erzwingung, oft unter Namen wie Structured Output geführt. Hier wird ein Schema mitgegeben, und die Erzeugung wird so eingeschränkt, dass nur schemakonforme Ausgaben entstehen können. Das eliminiert eine ganze Fehlerklasse: falsche Feldnamen, fehlende Pflichtfelder, falsche Typen. Wo verfügbar, ist Schema-Erzwingung die richtige Wahl, und der JSON-Mode nur noch ein Rückfall für Anbieter, die nichts Besseres können.

    Wichtig ist die Einschränkung: Schema-Erzwingung garantiert Form, nicht Wahrheit. Ein Modell kann ein perfekt schemakonformes Objekt mit inhaltlich falschen Werten füllen. Die Erzwingung löst das Parsing-Problem, nicht das Qualitätsproblem.

    Validierung als zweite Verteidigungslinie

    Auch mit Schema-Erzwingung gehört zwischen Modellantwort und Geschäftslogik eine eigene Validierungsschicht. Im TypeScript-Umfeld hat sich dafür Zod etabliert, in Python Pydantic. Das Prinzip ist in beiden Fällen dasselbe: Das Schema existiert als Quelltext im eigenen Projekt, die Antwort wird dagegen geparst, und erst das validierte Objekt betritt die Anwendung.

    Diese Schicht leistet drei Dinge, die die Erzwingung beim Anbieter nicht leisten kann:

    • Fachliche Regeln: Ein Datum kann syntaktisch gültig und trotzdem in der Vergangenheit liegen, obwohl ein Liefertermin gefragt war. Solche Prüfungen gehören in die eigene Validierung.
    • Unabhängigkeit vom Anbieter: Wer das Modell wechselt, behält dieselbe Verteidigungslinie. Die Garantien der Anbieter unterscheiden sich, das eigene Schema bleibt.
    • Saubere Fehlerbehandlung: Eine fehlgeschlagene Validierung ist ein definierter Zustand mit definiertem Verhalten, kein unbehandelter Absturz irgendwo im Code.

    Die Faustregel lautet: Die Modellantwort ist Nutzereingabe. Niemand würde ein Formularfeld ungeprüft in die Datenbank schreiben. Für Modellantworten gilt derselbe Standard.

    Verweigerungen und abgeschnittene Antworten

    Zwei Sonderfälle brechen strukturierte Outputs regelmäßig, und beide werden gerne übersehen. Der erste ist die Verweigerung: Das Modell lehnt eine Anfrage aus Sicherheitsgründen ab oder erklärt, dass die Aufgabe mit den gegebenen Informationen nicht lösbar ist. Manche Schnittstellen signalisieren das über ein eigenes Feld, andere schreiben die Ablehnung mitten in die Struktur. Die Anwendung braucht dafür einen definierten Pfad, etwa ein optionales Statusfeld im eigenen Schema, das den Fall sauber transportiert, statt ihn in einem Textfeld zu verstecken.

    Der zweite ist die abgeschnittene Antwort: Wenn das Ausgabelimit erreicht wird, endet die Erzeugung mitten im Objekt. Das Ergebnis ist ungültiges JSON, und zwar auch bei aktivierter Schema-Erzwingung, denn die kann nur einschränken, was erzeugt wird, nicht erzwingen, dass die Erzeugung zu Ende kommt. Deshalb gehört der Abbruchgrund der Antwort immer geprüft. Wurde wegen Längenlimit abgebrochen, hilft kein Reparaturversuch am JSON, sondern nur eine neue Anfrage mit höherem Limit oder eine Aufgabe, die kleinere Ausgaben erzeugt, etwa durch Aufteilung in mehrere Aufrufe.

    Schema-Versionierung nicht vergessen

    Schemas leben. Felder kommen dazu, Enums bekommen neue Werte, Strukturen werden umgebaut. Ohne Versionierung entsteht ein schleichendes Problem: In Logs, Warteschlangen und Datenbanken liegen Antworten nach altem Schema, während der Code schon das neue erwartet. Bewährt hat sich ein explizites Versionsfeld in jeder gespeicherten Antwort und die Regel, Schemas nur abwärtskompatibel zu erweitern: neue Felder optional, alte Felder nie umdeuten. Wer das von Anfang an durchzieht, erspart sich später Migrationsläufe über historische Daten.

    Fallstricke bei verschachtelten Strukturen und Enums

    Zwei Muster verursachen in der Praxis überproportional viele Fehler. Das erste sind tief verschachtelte Strukturen. Je tiefer und optionaler ein Schema, desto mehr Spielraum hat das Modell, Inhalte an der falschen Stelle abzulegen, und desto schwerer ist die Validierungsmeldung zu deuten. Flache Schemas mit wenigen Ebenen sind fast immer die bessere Wahl. Wenn eine komplexe Struktur nötig ist, lohnt es sich, sie auf mehrere Aufrufe aufzuteilen, die jeweils einen einfachen Teil liefern.

    Das zweite Muster sind Enums. Modelle neigen dazu, plausible, aber nicht definierte Werte zu erfinden, besonders wenn die erlaubten Werte im Prompt nicht wiederholt werden oder semantisch nahe beieinander liegen. Hilfreich ist, die Enum-Werte sprechend zu benennen, ihre Bedeutung kurz zu beschreiben und einen expliziten Restwert wie eine Kategorie für Sonstiges vorzusehen. Ohne Restwert quetscht das Modell Grenzfälle in die nächstbeste Kategorie, und die Auswertung wird unbemerkt unsauber.

    Fazit

    Zuverlässige strukturierte Outputs entstehen nicht durch einen einzelnen Mechanismus, sondern durch gestaffelte Absicherung: Schema-Erzwingung beim Anbieter, wo verfügbar, eine eigene Validierungsschicht mit fachlichen Regeln, definierte Pfade für Verweigerungen und abgeschnittene Antworten, versionierte Schemas und bewusst einfache Strukturen. Wer die Modellantwort konsequent wie ungeprüfte Eingabe behandelt, verwandelt die häufigste Fehlerquelle von LLM-Integrationen in einen kontrollierten, messbaren Teil des Systems.

    Sprechen wir über Ihr Vorhaben.

    Unverbindliches Erstgespräch. Wir melden uns zeitnah bei Ihnen.

    Erstgespräch anfragen →