← Tutti gli articoli

JSON Patch vs JSON Merge Patch: RFC 6902 vs 7396

JSON Patch (RFC 6902) invia operazioni esplicite; JSON Merge Patch (RFC 7396) sovrappone un oggetto parziale. Confronta i due con esempi e scegli quello giusto.

Quando un'API HTTP deve aggiornare parte di una risorsa, due standard IETF si contendono il lavoro: JSON Merge Patch (RFC 7396) e JSON Patch (RFC 6902). Sembrano simili ma funzionano in modo molto diverso —— Merge Patch sovrappone un oggetto parziale, mentre JSON Patch invia un elenco esplicito di operazioni. Questa guida mostra come funziona ciascuno, li confronta testa a testa e ti aiuta a scegliere quello giusto.

Il problema: aggiornamenti parziali

Una richiesta PUT sostituisce un'intera risorsa, il che è sprecone e rischioso quando vuoi cambiare solo un campo. Il metodo HTTP PATCH esiste per aggiornamenti parziali —— ma PATCH non definisce un formato di body. È quello che questi due standard forniscono.

JSON Merge Patch (RFC 7396)

Un Merge Patch è semplicemente una versione parziale del documento di destinazione. Il server lo sovrappone: le key nel patch vengono impostate, le key messe a null vengono cancellate, e le key non menzionate restano intatte.

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

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

// Risultato
{ "title": "Hello World", "author": "Ada", "tags": ["a", "b"] }
//   ^ title aggiornato     ^ author intatto         ^ draft cancellato (era null)

È intuitivo e compatto. La fregatura: poiché null significa «cancella», non puoi usare Merge Patch per impostare un valore a null, e gli array si possono solo sostituire interamente —— non c'è modo di cambiare un singolo elemento dell'array.

JSON Patch (RFC 6902)

Un JSON Patch è un array ordinato di operazioni, ognuna che mira a una posizione con un path JSON Pointer. È esplicito e preciso:

// 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" }
]

Le sei operazioni:

opEffetto
addAggiungere un valore (o append a un array con /-)
removeCancellare il valore a un path
replaceSostituire il valore a un path
moveSpostare un valore da un path a un altro
copyCopiare un valore in un altro path
testAsserire un valore (aborta l'intero patch se fallisce)

L'op test abilita aggiornamenti sicuri e atomici: se il documento non è nello stato atteso, l'intero patch viene rifiutato —— utile per controllo di concorrenza ottimistico.

Confronto testa a testa

JSON Merge PatchJSON Patch
RFC73966902
Content-Typeapplication/merge-patch+jsonapplication/json-patch+json
LeggibilitàAlta —— sembra i datiMinore —— elenco di operazioni
Può impostare un valore a nullNo (null significa cancellare)
Modificare un singolo elemento di arrayNo (sostituire l'intero array)Sì (per indice)
Aggiornamenti condizionali / atomiciNoSì (op test)
Move / copyNo
Ideale perSemplici aggiornamenti di campi di oggettoModifiche precise, consce degli array, atomiche

Quando usare cosa

  • JSON Merge Patch —— quando i client aggiornano per lo più campi di oggetto di primo livello e dai valore a un body che si legge come la risorsa. Ottimo per impostazioni semplici e aggiornamenti di profilo. Solo ricorda che non puoi impostare campi a null né modificare item di array.
  • JSON Patch —— quando devi modificare elementi di array, spostare o copiare valori, impostare campi a null, o applicare cambiamenti atomicamente con una precondizione. La scelta standard per editing collaborativo e change set amici dell'audit.

Semantica HTTP PATCH: idempotenza e header

Due dettagli HTTP che spesso fregano i team che mettono in produzione un endpoint PATCH:

  • PATCH non deve essere idempotente (a differenza di PUT). Un JSON Patch con {"op":"add","path":"/items/-","value":...} fa append —— applicarlo due volte aggiunge due volte. Se vuoi retry sicuri, o usa un'op test per asserire prima lo stato, o progetta le tue op così che riapplicarle sia no-op (usa replace su un path fisso invece di add su /items/-).
  • Usa il Content-Type giusto. RFC 6902 = application/json-patch+json; RFC 7396 = application/merge-patch+json. I server di solito si ramificano su questo.
  • Concorrenza ottimistica. Combina un'op test di JSON Patch (o un header If-Match con ETag) così writer concorrenti non possono sovrascriversi silenziosamente.

Librerie da conoscere

Per JSON Patch, fast-json-patch è il pacchetto npm di fatto —— applica, genera (diff di due documenti per produrre un patch) e osserva (traccia cambiamenti a un oggetto osservato). Per JSON Merge Patch, le regole sono abbastanza piccole da scriverle inline, ma json-merge-patch le implementa con i casi limite della cancellazione tramite null gestiti.

Applicare patch nel codice

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

// JSON Merge Patch è banale da applicare per ricorsione, ma una libreria
// (es. json-merge-patch) gestisce correttamente le regole di cancellazione tramite null.

Dopo aver applicato un patch, puoi confermare che la modifica è esattamente quella che intendevi facendo diff di prima e dopo —— vedi Come confrontare due file JSON o incolla entrambi in JSON Diff.

Domande frequenti

Qual è la differenza tra JSON Patch e JSON Merge Patch?

JSON Merge Patch (RFC 7396) è una copia parziale del documento dove null cancella una key. JSON Patch (RFC 6902) è un array esplicito di operazioni (add, remove, replace, move, copy, test) che mirano a path JSON Pointer. Merge Patch è più semplice; JSON Patch è più potente.

Perché JSON Merge Patch non può impostare un campo a null?

Perché in Merge Patch null è il segnale per cancellare una key. Se devi memorizzare un valore null vero, usa JSON Patch con un'op replace.

Quale Content-Type devo usare?

application/merge-patch+json per Merge Patch e application/json-patch+json per JSON Patch, entrambi inviati con il metodo HTTP PATCH.

Come modifico un elemento di un array?

Usa JSON Patch con un path come /items/2, o fai append con /items/-. Merge Patch può solo sostituire l'intero array.

Strumenti & letture correlate