Verschachtelt schreiben
Kurzantwort: Sie können Kindobjekte im selben Request anlegen, ändern oder
nur verknüpfen — ob das erlaubt ist, entscheidet das Modell pro Beziehung. Ein
Kind ohne id soll angelegt werden, eines mit id verweist auf ein
vorhandenes. Ist die nötige Erlaubnis nicht gesetzt, wird der Eintrag entweder
abgelehnt oder stillschweigend verworfen.
Warum das nützlich ist
Abschnitt betitelt „Warum das nützlich ist“Ein Auftrag mit Positionen, ein Kunde mit Adressen, ein Audit mit Fragen und Antworten: Sie schicken den Baum in einem Request, statt fünf Aufrufe zu orchestrieren und bei einem Fehler in der Mitte aufräumen zu müssen. Alles läuft in derselben Transaktion — geht etwas schief, ist nichts geschrieben.
Die vier Fälle
Abschnitt betitelt „Die vier Fälle“flowchart TB
A["Kindobjekt im Payload"] --> B{"hat es eine id?"}
B -->|nein| C{"darf über diese<br/>Beziehung angelegt werden?"}
C -->|ja| D["wird neu angelegt<br/>und verknüpft"]
C -->|nein| E["400 — oder stilles Verwerfen"]
B -->|ja| F{"darf über diese<br/>Beziehung geändert werden?"}
F -->|ja| G["das vorhandene Objekt<br/>wird mitgeschrieben"]
F -->|nein| H["wird nur verknüpft,<br/>Inhalt bleibt unberührt"]
| Kind im Payload | Modell erlaubt | Ergebnis |
|---|---|---|
ohne id | Anlegen | wird angelegt und verknüpft |
ohne id | kein Anlegen | 400 `recursive-create-not-allowed |
mit id | Ändern | vorhandenes Objekt wird mitgeschrieben |
mit id | kein Ändern | wird nur verknüpft, Inhalt bleibt |
Ob ein nicht erlaubter Fall zum Fehler führt oder still übergangen wird, hängt an der Betriebsart des Servers. Verlassen Sie sich nicht darauf: Wenn ein verschachteltes Objekt spurlos verschwindet, ist meist genau das die Ursache.
Anlegen mit Kindern
Abschnitt betitelt „Anlegen mit Kindern“POST /crm/order/create{ "data": { "orderNumber": "2026-0042", "customer": { "id": "5a2b…" }, "items": [ { "article": "A-100", "quantity": 2, "price": 19.90 }, { "article": "A-200", "quantity": 1, "price": 149.00 } ] }, "response": ["id", "orderNumber", { "field": "items", "response": ["id", "article"] }]}customerhat eineid→ bestehender Kunde wird verknüpft, nicht verändert.itemshaben keineid→ werden angelegt.- Der
responseliest den fertigen Baum gleich zurück; Sie bekommen die erzeugten IDs, ohne nochmal anzufragen.
Verknüpfen statt anlegen
Abschnitt betitelt „Verknüpfen statt anlegen“Nur die id genügt:
{ "data": { "customer": { "id": "5a2b…" } } }Weitere Felder daneben würden — sofern das Modell Änderungen erlaubt — den
Kunden mitändern. Wenn Sie das nicht wollen, schicken Sie ausschließlich die
id.
Listen sind ein Zielzustand
Abschnitt betitelt „Listen sind ein Zielzustand“Eine gesendete Liste beschreibt, wie die Beziehung danach aussehen soll:
PATCH /crm/order/update/{id}{ "data": { "id": "order-1", "items": [ { "id": "item-1", "quantity": 5 }, { "article": "A-300", "quantity": 1, "price": 9.90 } ] }, "response": ["id"]}Das bedeutet dreierlei auf einmal:
item-1bleibt und bekommtquantity: 5.- Der Eintrag ohne
idwird neu angelegt. - Jede andere Position verschwindet — abhängige Kinder werden gelöscht, eigenständige Objekte nur abgekoppelt.
Wollen Sie nur eine Position ändern, ohne die übrigen zu gefährden, ändern Sie die Position direkt über ihren eigenen Endpunkt.
| Absicht | so |
|---|---|
| eine Position ändern | PATCH /crm/orderitem/update/{itemId} |
| Positionen als Ganzes setzen | items im Auftrag senden |
| alle Positionen entfernen | "items": [] im PATCH |
| Positionen unangetastet lassen | items im PATCH weglassen |
Abstrakte Typen brauchen @type
Abschnitt betitelt „Abstrakte Typen brauchen @type“Zeigt eine Beziehung auf ein abstraktes Modell, muss beim Anlegen der konkrete Typ dabeistehen:
{ "data": { "contacts": [ { "@type": "crm.emailcontact", "address": "info@muster.de" }, { "@type": "crm.phonecontact", "number": "+49 …" } ] }}Fehlt @type, kommt 400 missing-type-for-abstract-field|<feld>. Beim
Verknüpfen über eine id ist er entbehrlich.
Wie tief darf es gehen?
Abschnitt betitelt „Wie tief darf es gehen?“Beliebig — die Regeln gelten auf jeder Ebene neu. Ein PATCH auf den Auftrag kann eine neue Position anlegen, die ihrerseits ein neues Unterobjekt bekommt. Für jede Ebene gilt die Erlaubnis dieser Beziehung, und für jedes neue Objekt gelten die Anlege-Regeln, während der Auftrag selbst nach Änderungs-Regeln behandelt wird.
Praktisch: Halten Sie es flach. Zwei Ebenen sind gut beherrschbar, bei vier wird die Fehlersuche mühsam.
Die Gegenrichtung nicht mitschicken
Abschnitt betitelt „Die Gegenrichtung nicht mitschicken“Zeigt das Kind auf seinen Elternteil zurück (item.order), lassen Sie dieses
Feld weg. Die Zuordnung verwaltet der Elternteil; ein mitgeschicktes
Rückverweis-Feld wird ignoriert oder stiftet Verwirrung.
Fehler beim verschachtelten Schreiben
Abschnitt betitelt „Fehler beim verschachtelten Schreiben“| Antwort | Bedeutung |
|---|---|
| 400 `recursive-create-not-allowed | |
| 400 `missing-type-for-abstract-field | |
| 404 `missing-object | |
422 mit Pfad items.0.price | Validierung eines Kindes — der Pfad zeigt, welches |
Bei jedem dieser Fehler ist nichts geschrieben, auch nicht die schon verarbeiteten Teile. Siehe Transaktionen aus Client-Sicht.
Details
Abschnitt betitelt „Details“Die vollständigen Regeln samt Löschverhalten stehen unter Beziehungen und Schreibsemantik.