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

Two standard ways to send just the changes to a JSON document — how each works, the gotchas (arrays, null), and which to reach for.

When a client wants to update one field of a resource, sending the entire object back is wasteful and race-prone. Two IETF standards let you send only the change instead: JSON Patch (RFC 6902) and JSON Merge Patch (RFC 7396). They solve the same problem in very different ways, and picking the wrong one leads to surprises — like an array you meant to tweak getting wiped, or a field you can't set to null. Here's how each works and when to use it.

A shared starting document

Every example below patches this object:

{
  "name": "Ada",
  "age": 36,
  "tags": ["admin", "beta"],
  "address": { "city": "London", "zip": "EC1" }
}

JSON Merge Patch (RFC 7396): looks like the target

A merge patch is a partial copy of the document. The rules are simple: a key that's present is set (recursively, for objects); a key whose value is null is deleted; a key that's absent is left untouched. To rename the city, drop the age, and add a tag set:

{
  "age": null,
  "address": { "city": "Berlin" }
}

Result: age is removed, address.city becomes "Berlin" (and address.zip is kept, because objects merge), while name and tags are unchanged. That readability is the appeal — but it has two sharp edges:

  • You can't set a value to null, because null means “delete.”
  • Arrays are replaced wholesale. Sending "tags": ["admin"] overwrites the entire array — there's no way to add or remove a single element.

JSON Patch (RFC 6902): a list of operations

A JSON Patch is an ordered array of operations, each with an op and a path (a JSON Pointer). The same edits, plus a precise array change:

[
  { "op": "remove",  "path": "/age" },
  { "op": "replace", "path": "/address/city", "value": "Berlin" },
  { "op": "add",     "path": "/tags/-", "value": "early-access" }
]

The six operations are add, remove, replace, move, copy, and test. The /tags/- path appends to an array; /tags/0 would target the first element. test asserts a value before applying (useful for optimistic concurrency — the patch fails if the document isn't what you expected). Operations apply in order and are meant to be atomic: if one fails, none should take effect.

Side-by-side: which to choose

JSON Merge Patch (7396)JSON Patch (6902)
ShapePartial document that mirrors the targetArray of explicit operations
Delete a fieldSet it to null{ "op": "remove", "path": "…" }
Set a value to nullNot possibleYes — replace with null
Array elementsWhole array replacedAdd / remove / replace by index
PreconditionsNonetest op (optimistic concurrency)
ReadabilityHigh — looks like the dataLower — verbose op list
Media typeapplication/merge-patch+jsonapplication/json-patch+json

Rule of thumb: reach for Merge Patch when you're setting a handful of object fields and never need element-level array edits or literal nulls — it's the friendlier default for most PATCH APIs. Reach for JSON Patch when you need precise array operations, move/copy, conditional test, or guaranteed ordering.

Applying patches in code

In JavaScript, fast-json-patch handles RFC 6902, and there are small libraries for 7396:

import { applyPatch } from "fast-json-patch";

const patch = [{ op: "replace", path: "/address/city", value: "Berlin" }];
const updated = applyPatch(doc, patch).newDocument;

In Python, use jsonpatch for 6902 and json-merge-patch for 7396:

import jsonpatch

patch = jsonpatch.JsonPatch([
    {"op": "replace", "path": "/address/city", "value": "Berlin"}
])
updated = patch.apply(doc)

Apply patches without code

When I'm working out a patch — or checking what an API will do before sending it — I test it in the browser first. Our free tools apply each spec live and client-side (disclosure: I built them): the JSON Patch tool applies RFC 6902 operations, and the JSON Merge Patch tool applies RFC 7396. To see what actually changed between two versions of a document, the JSON Compare tool gives a semantic diff.

FAQs

What's the difference between JSON Patch and JSON Merge Patch?
JSON Patch (6902) is an ordered array of operations (add/remove/replace/move/copy/test). JSON Merge Patch (7396) is a partial document where present keys are set and null deletes. Patch is precise; Merge Patch is simpler.

When should I use JSON Merge Patch?
For simple field updates where you don't need element-level array operations or to store a literal null.

How do I delete a field with JSON Merge Patch?
Set it to null — RFC 7396 treats null as “remove this key.”

Can JSON Merge Patch modify a single array element?
No — it replaces the whole array. Use JSON Patch to target an index like /items/2.

What content types do they use?
application/json-patch+json for 6902 and application/merge-patch+json for 7396, both with HTTP PATCH.

Related articles