# What Is JSON Patch? — RFC 6902 Operations, JSON Pointer and Examples

Canonical: https://commareports.com/glossary/json-patch
Published: 2026-10-16

> JSON Patch (RFC 6902) describes a change to a JSON document as a list of add, remove, replace, move, copy and test operations addressed with JSON Pointer paths like /checks/0/timeout_ms. The six operations with examples, how it differs from JSON Merge Patch, and how to generate one from two files.

# JSON Patch

**JSON Patch is a standard way to write down a change to a JSON
document as a list of operations.** It is defined in
[RFC 6902](https://www.rfc-editor.org/rfc/rfc6902), and a patch is
itself plain JSON:

```json
[
  { "op": "replace", "path": "/version", "value": "2.14.0" },
  { "op": "add", "path": "/features/-", "value": "klarna" },
  { "op": "remove", "path": "/owner/oncall" }
]
```

Applied in order to the original document, those three operations bump
the version, append to an array and delete a key. Nothing else in the
document is touched.

## The six operations

| Operation | What it does                                                                       | Example                                              |
| --------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `add`     | Inserts a value. On an object key it sets it; in an array it inserts at that index | `{"op":"add","path":"/tags/0","value":"new"}`        |
| `remove`  | Deletes the value at the path                                                      | `{"op":"remove","path":"/owner/oncall"}`             |
| `replace` | Overwrites a value that must already exist                                         | `{"op":"replace","path":"/replicas","value":6}`      |
| `move`    | Removes from one path and adds at another                                          | `{"op":"move","from":"/draft","path":"/final"}`      |
| `copy`    | Copies a value to another path                                                     | `{"op":"copy","from":"/defaults","path":"/staging"}` |
| `test`    | Fails the whole patch unless the value equals the one given                        | `{"op":"test","path":"/version","value":"2.13.0"}`   |

Two details catch people out. In an array, `add` _inserts_ and shifts
everything after it — it does not overwrite; use `replace` for that.
And a path ending in `/-` means "after the last element", which is how
you append without knowing the length.

The patch is atomic: if any operation fails — a `replace` on a path
that does not exist, a `test` that does not match — the whole patch is
rejected and the document is left as it was. Putting a `test` first is
the cheap way to make a patch refuse to apply to a document someone
else has changed in the meantime.

## JSON Pointer: the path syntax

Every `path` and `from` in a patch is a **JSON Pointer**
([RFC 6901](https://www.rfc-editor.org/rfc/rfc6901)): slash-separated
steps from the root, with array indexes as plain numbers.

| JSON Pointer           | Points at                                  |
| ---------------------- | ------------------------------------------ |
| `""` (empty string)    | The whole document                         |
| `/version`             | The `version` key at the top level         |
| `/checks/0/timeout_ms` | `timeout_ms` of the first item in `checks` |
| `/headers/x~1request`  | The key `x/request` — `/` is written `~1`  |
| `/a~0b`                | The key `a~b` — `~` is written `~0`        |

A pointer names exactly one value and has no wildcards or filters.
That is the difference from [JSONPath](/glossary/jsonpath), which is a
query (`$.checks[*].name`) that can match many values at once. The
same location reads `/checks/2/error` as a pointer and
`$.checks[2].error` as JSONPath.

## JSON Patch vs JSON Merge Patch

There is a second, simpler format with a confusingly similar name.
**JSON Merge Patch** ([RFC 7396](https://www.rfc-editor.org/rfc/rfc7396))
is just a partial document that gets merged in:

```json
{ "version": "2.14.0", "owner": { "oncall": null } }
```

Keys present overwrite, `null` deletes, everything else is left alone.
It is easy to write by hand, but it has two blind spots: it cannot set a
value _to_ `null` (that means delete), and it cannot change one item
inside an array — arrays are replaced whole. JSON Patch has neither
limit, which is why APIs that edit nested lists — Kubernetes
`kubectl patch --type=json`, many REST `PATCH` endpoints using the
`application/json-patch+json` media type — accept it.

## Where you meet it

- **HTTP `PATCH` requests**, with `Content-Type: application/json-patch+json`.
- **Kubernetes**, for surgical edits to a resource's spec.
- **Config and infrastructure review**, where the patch _is_ the
  change someone has to approve.
- **Sync and undo**: store the patch instead of the whole document, and
  replay or invert it later.
- **Agents editing structured files**, where a short list of
  operations is easier to check than a rewritten file.

## Generating a patch from two files

Writing a patch by hand is fine for three operations and error-prone
for thirty. Comma's free [JSON diff](/tools/json-diff) compares two
documents structurally — key order and formatting ignored, arrays of
records matched by `id` — and its JSON Patch tab gives you the
RFC 6902 patch that turns the left document into the right one. It
uses `add`, `remove` and `replace` only, addresses arrays by index,
and runs entirely in your browser.

If the change is one a reviewer has to sign off, publish the diff:
it becomes a link where they comment on the exact path they are
questioning, with the patch attached underneath.

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited
revision history.

**[Open the JSON diff →](/tools/json-diff)**

### Related

- [JSONPath](/glossary/jsonpath) · [NDJSON](/glossary/ndjson) · [Byte order mark](/glossary/byte-order-mark)
- [JSON diff](/tools/json-diff) · [JSON viewer](/tools/json-viewer) · [JSON formatter](/tools/json-formatter)
- [Glossary](/glossary)
