← Alle Artikel

JSON Patch vs. JSON Merge Patch: RFC 6902 vs. 7396

JSON Patch (RFC 6902) sendet explizite Operationen; JSON Merge Patch (RFC 7396) legt ein Teil-Objekt darüber. Beide mit Beispielen vergleichen und das richtige wählen.

Wenn eine HTTP-API einen Teil einer Ressource aktualisieren muss, konkurrieren zwei IETF-Standards um den Job: JSON Merge Patch (RFC 7396) und JSON Patch (RFC 6902). Sie sehen ähnlich aus, funktionieren aber sehr unterschiedlich —— Merge Patch überlagert ein Teilobjekt, während JSON Patch eine explizite Liste von Operationen sendet. Diese Anleitung zeigt, wie beide funktionieren, vergleicht sie direkt und hilft dir, das richtige zu wählen.

Das Problem: Teilaktualisierungen

Eine PUT-Anfrage ersetzt eine ganze Ressource, was verschwenderisch und riskant ist, wenn du nur ein Feld ändern willst. Die HTTP-PATCH-Methode existiert für Teilaktualisierungen —— PATCH definiert aber kein Body-Format. Genau das liefern diese beiden Standards.

JSON Merge Patch (RFC 7396)

Ein Merge Patch ist einfach eine Teilversion des Zieldokuments. Der Server überlagert es: Keys im Patch werden gesetzt, auf null gesetzte Keys werden gelöscht, und nicht erwähnte Keys bleiben unangetastet.

// Original
{ "title": "Hello", "author": "Ada", "tags": ["a", "b"], "draft": true }

// Merge Patch body (Content-Type: application/merge-patch+json)
{ "title": "Hello World", "draft": null }

// Ergebnis
{ "title": "Hello World", "author": "Ada", "tags": ["a", "b"] }
//   ^ title aktualisiert     ^ author unverändert      ^ draft gelöscht (war null)

Intuitiv und kompakt. Der Haken: weil null „löschen" bedeutet, kannst du Merge Patch nicht nutzen, um einen Wert auf null zu setzen, und Arrays können nur komplett ersetzt werden —— es gibt keinen Weg, ein einzelnes Array-Element zu ändern.

JSON Patch (RFC 6902)

Ein JSON Patch ist ein geordnetes Array von Operationen, jede zielt mit einem JSON Pointer-Pfad auf eine Stelle. Explizit und präzise:

// JSON Patch body (Content-Type: application/json-patch+json)
[
  { "op": "replace", "path": "/title", "value": "Hello World" },
  { "op": "remove",  "path": "/draft" },
  { "op": "add",     "path": "/tags/-", "value": "c" },
  { "op": "test",    "path": "/author", "value": "Ada" }
]

Die sechs Operationen:

opWirkung
addEinen Wert hinzufügen (oder mit /- an ein Array anhängen)
removeDen Wert an einem Pfad löschen
replaceDen Wert an einem Pfad ersetzen
moveEinen Wert von einem Pfad zu einem anderen verschieben
copyEinen Wert zu einem anderen Pfad kopieren
testEinen Wert behaupten (bei Misserfolg den ganzen Patch abbrechen)

Die test-Op ermöglicht sichere, atomare Updates: Ist das Dokument nicht im erwarteten Zustand, wird der gesamte Patch abgelehnt —— nützlich für optimistische Concurrency Control.

Direktvergleich

JSON Merge PatchJSON Patch
RFC73966902
Content-Typeapplication/merge-patch+jsonapplication/json-patch+json
LesbarkeitHoch —— sieht aus wie die DatenNiedriger —— Liste von Operationen
Kann Wert auf null setzenNein (null bedeutet löschen)Ja
Einzelnes Array-Element ändernNein (gesamtes Array ersetzen)Ja (per Index)
Bedingte / atomare UpdatesNeinJa (test-Op)
Move / copyNeinJa
Am besten fürEinfache Objekt-Feld-UpdatesPräzise, array-bewusste, atomare Bearbeitungen

Wann was nutzen

  • JSON Merge Patch —— wenn Clients hauptsächlich Top-Level-Objektfelder aktualisieren und du einen Body schätzt, der wie die Ressource liest. Super für einfache Einstellungen und Profil-Updates. Denk nur dran, dass du Felder nicht auf null setzen oder Array-Items bearbeiten kannst.
  • JSON Patch —— wenn du Array-Elemente bearbeiten, Werte verschieben oder kopieren, Felder auf null setzen oder Änderungen mit Vorbedingung atomar anwenden musst. Die Standardwahl für kollaboratives Editing und audit-freundliche Change Sets.

HTTP-PATCH-Semantik: Idempotenz und Header

Zwei HTTP-Details, die Teams beim Ausliefern eines PATCH-Endpoints oft erwischen:

  • PATCH muss nicht idempotent sein (anders als PUT). Ein JSON Patch mit {"op":"add","path":"/items/-","value":...} fügt an —— ihn zweimal anzuwenden, fügt zweimal hinzu. Wenn du sichere Retries willst, nutze entweder eine test-Op, um den Zustand zuerst zu behaupten, oder gestalte deine Ops so, dass das erneute Anwenden ein No-op ist (nutze replace auf einem festen Pfad statt add auf /items/-).
  • Nutze den richtigen Content-Type. RFC 6902 = application/json-patch+json; RFC 7396 = application/merge-patch+json. Server verzweigen üblicherweise darauf.
  • Optimistische Concurrency. Kombiniere eine JSON-Patch-test-Op (oder einen If-Match-ETag-Header), damit gleichzeitige Schreiber sich nicht still gegenseitig überschreiben.

Wissenswerte Libraries

Für JSON Patch ist fast-json-patch das De-facto-NPM-Paket —— es wendet an, generiert (diff zweier Dokumente zur Patch-Erzeugung) und beobachtet (verfolgt Änderungen an einem beobachteten Objekt). Für JSON Merge Patch sind die Regeln klein genug, um sie inline zu schreiben, aber json-merge-patch implementiert sie mit den null-Löschungs-Grenzfällen korrekt.

Patches im Code anwenden

// JavaScript —— fast-json-patch implementiert RFC 6902
import { applyPatch } from 'fast-json-patch';
const updated = applyPatch(document, patchOps).newDocument;

// JSON Merge Patch ist trivial per Rekursion anzuwenden, aber eine Library
// (z. B. json-merge-patch) handhabt die null-Löschungsregeln korrekt.

Nach dem Anwenden eines Patches kannst du bestätigen, dass die Änderung genau das ist, was du beabsichtigt hast, indem du Vor- und Nachzustand diffst —— siehe Wie man zwei JSON-Dateien vergleicht oder füge beide in JSON Diff ein.

Häufig gestellte Fragen

Was ist der Unterschied zwischen JSON Patch und JSON Merge Patch?

JSON Merge Patch (RFC 7396) ist eine Teilkopie des Dokuments, in der null einen Key löscht. JSON Patch (RFC 6902) ist ein explizites Array von Operationen (add, remove, replace, move, copy, test), das JSON-Pointer-Pfade adressiert. Merge Patch ist einfacher; JSON Patch ist mächtiger.

Warum kann JSON Merge Patch ein Feld nicht auf null setzen?

Weil null in Merge Patch das Signal ist, einen Key zu löschen. Wenn du einen echten null-Wert speichern musst, nutze JSON Patch mit einer replace-Op.

Welchen Content-Type sollte ich nutzen?

application/merge-patch+json für Merge Patch und application/json-patch+json für JSON Patch, beide mit der HTTP-PATCH-Methode gesendet.

Wie editiere ich ein Element eines Arrays?

Nutze JSON Patch mit einem Pfad wie /items/2, oder hänge mit /items/- an. Merge Patch kann nur das gesamte Array ersetzen.

Verwandte Tools & Lektüre