structura.Runs in your browser

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

  1. Open the JSON diff tool. Paste or open the original document in A · Original and the target document in B · Updated.
  2. 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.
  3. 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.
  4. 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.

Generate a patch from your JSON

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 pathPatch pointerWhy
$["env"]["LOG_LEVEL"]/env/LOG_LEVELEach property becomes one segment.
$["ports"][2]/ports/2Array indexes are written as numbers.
$["owners/team"]/owners~1teamA slash inside a name is written ~1.
$["a~b"]/a~0bA 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

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

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.