JSON field notes · 02
Generate a JSON Patch from two JSON documents
Give Structura the original and the updated JSON. Besides a readable diff, it writes the RFC 6902 operations that turn the first document into the second, ready for an HTTP PATCH body or a migration script.
Create the patch
- Open the JSON diff tool. Paste or open the original document in A · Original and the target document in B · Updated.
- Clear Match array items by. The example on the tool page fills in
id, and a patch cannot be written while arrays are paired by id. - Check the list of changes. Every entry shows the path, the old value and the new value, so you can confirm the patch does what you expect before you download it.
- Select Download JSON Patch. The file is
json-patch.json, an array of operations with two-space indentation.
A patch only describes the difference between these two documents. Applied to any other document, an operation may fail (for example, removing a path that does not exist) or produce a different result.
Worked example: a service configuration
The version, replica count and log level change, one environment variable is replaced by another, two ports are dropped, and one property name contains a slash.
A · Original
{
"name": "billing-api",
"version": "1.4.0",
"replicas": 2,
"env": {
"LOG_LEVEL": "info",
"FEATURE_X": "off"
},
"ports": [8080, 8443, 9090],
"owners/team": "payments"
}B · Updated
{
"name": "billing-api",
"version": "1.5.0",
"replicas": 3,
"env": {
"LOG_LEVEL": "warn",
"REGION": "eu-west-1"
},
"ports": [8080],
"owners/team": "payments-core"
}The diff lists 8 changes. The downloaded patch has the same 8 operations:
[
{ "op": "replace", "path": "/version", "value": "1.5.0" },
{ "op": "replace", "path": "/replicas", "value": 3 },
{ "op": "replace", "path": "/env/LOG_LEVEL", "value": "warn" },
{ "op": "remove", "path": "/env/FEATURE_X" },
{ "op": "add", "path": "/env/REGION", "value": "eu-west-1" },
{ "op": "remove", "path": "/ports/2" },
{ "op": "remove", "path": "/ports/1" },
{ "op": "replace", "path": "/owners~1team", "value": "payments-core" }
]The real file puts each property on its own line; it is compressed here to fit. Operations are applied in order, and the result equals document B.
How paths become JSON Pointers
The on-screen report uses bracket paths such as $["env"]["LOG_LEVEL"]. The patch uses JSON Pointer (RFC 6901), where each segment is preceded by /:
| Report path | Patch pointer | Why |
|---|---|---|
$["env"]["LOG_LEVEL"] | /env/LOG_LEVEL | Each property becomes one segment. |
$["ports"][2] | /ports/2 | Array indexes are written as numbers. |
$["owners/team"] | /owners~1team | A slash inside a name is written ~1. |
$["a~b"] | /a~0b | A tilde inside a name is written ~0. |
$ | "" (empty) | The whole document, used when the root itself changes type or value. |
If you build pointers by hand, escape ~ before /; doing it the other way round turns / into ~01.
Array rules in the patch
- Removed items at the end of an array are removed from the highest index down (
/ports/2before/ports/1), so each index still points at the right item when it is applied. - Added items are written with their final index in ascending order, so each
addinserts at a position that already exists. - Positional comparison treats a deletion in the middle as a series of replaced values plus a removal at the end. The patch is correct, just longer than a human would write it.
- Ignore array order replaces a differing array as a whole with the updated array. An array that only changed order produces no operation, so the patched document keeps the original order.
- Match array items by (for example
id) gives a clearer report, but no patch: the pairing says which items correspond, not where they should sit.
For a full walk-through of the three array modes on one document, see comparing JSON while ignoring array order.
Apply the patch
Any RFC 6902 implementation can apply the file. Three common ways:
JavaScript (fast-json-patch)
import { applyPatch } from 'fast-json-patch';
const updated = applyPatch(structuredClone(original), patch).newDocument;Python (jsonpatch)
import json, jsonpatch
patch = json.load(open('json-patch.json'))
updated = jsonpatch.apply_patch(original, patch)HTTP PATCH
curl -X PATCH https://api.example.com/services/billing-api \ -H 'Content-Type: application/json-patch+json' \ --data @json-patch.json
Only send a patch to an API that documents JSON Patch support. To guard against a document that changed since you compared it, you can add a test operation at the top by hand, for example { "op": "test", "path": "/version", "value": "1.4.0" }. If the test fails, RFC 6902 says the patch as a whole is not successful; check how your library or API rolls back a failed patch.
What the generated patch does not do
- It uses
add,removeandreplaceonly. There are nomove,copyortestoperations, so a renamed property is a remove followed by an add. - Keys listed in Ignore keys are left out. Applying the patch keeps the original values of those keys.
- A report is limited to 2,000 changes. When that limit is reached the patch is not offered, because it would be incomplete.
- Values are written as JavaScript reads them. An integer with more than 15–16 significant digits may lose precision; the editor warns about such numbers.
- Both documents must be valid JSON. Files are limited to 5 MB each.
The documents are compared in this browser tab, and the patch file is created there. See the privacy notice.
Questions
Which JSON Patch operations does Structura generate?
add, remove and replace. It does not emit move, copy or test. A renamed property appears as a remove followed by an add.
Why is Download JSON Patch disabled?
The patch is not offered when Match array items by pairs at least one array by id, because the pairing does not say where an item should sit, or when the report stopped at its 2,000-change limit. Clear Match array items by, or compare a smaller section.
Does the patch include keys I chose to ignore?
No. Ignored keys are skipped, so applying the patch keeps the original values of those keys and does not add ignored keys that exist only in the updated document.
What happens to arrays when Ignore array order is on?
An array whose contents differ is replaced as a whole with the updated array. An array that only changed order produces no operation, so the patched document keeps the original order.
Is my JSON uploaded to create the patch?
No. Both documents are parsed and compared in the browser tab and the patch file is created there. Only your comparison options are remembered in this browser.
Reference
RFC 6902 — JSON Patch, RFC 6901 — JSON Pointer. The examples describe this tool’s output; check what your API or library expects before relying on a patch.