Original
Modified
Ctrl+Enter
Diff Result

Paste data on both sides to compare

Reference

JSON diff formats, key path notations, and CLI equivalents

The tool above runs JSON and YAML comparisons in the browser. The reference below catalogs the standardized diff formats (JSON Patch, JSON Merge Patch, JSON Pointer), the key-path notations used across the JSON tooling ecosystem, and the command-line invocations that produce equivalent output to the web interface.

Key path notations across the JSON tooling ecosystem

When a diff reports spec.containers[0].image, that path is one of several competing conventions for addressing a nested value inside a structured document. The same target (the first container's image field) looks different in every tool.

NotationExample pathStandardUsed by
Lodash-style dotspec.containers[0].imageNone (de facto)Diffpad, jsondiffpatch, Lodash _.get/_.set, most npm utilities
JSON Pointer/spec/containers/0/imageRFC 6901JSON Patch (RFC 6902), JSON Schema, OpenAPI $ref
JSONPath$.spec.containers[0].imageRFC 9535 (2024)jq, jsonpath-plus, kubectl -o jsonpath
jq path.spec.containers[0].imagejq grammarjq, yq (mikefarah and kislyuk variants)
XPath/spec/containers/container[1]/imageW3CXML-only, not applicable to JSON natively
GraphQL pathspec.containers.0.imageGraphQL spec error formatApollo, GraphQL response errors

JSON Pointer is the only one ratified by IETF for JSON value addressing. Diffpad uses Lodash-style dot notation because it pastes cleanly into Slack and PR comments without escape characters. JSON Pointer's leading slash and zero-indexed segments read like file paths and confuse non-engineers in the same thread.

JSON Pointer (RFC 6901) syntax rules

A JSON Pointer is a Unicode string that identifies one specific value inside a JSON document. The grammar fits on a card.

RulePointerResolves to
Empty string""The whole document
Single slash"/"The value at key "" (empty string key)
Top-level key"/foo"doc["foo"]
Nested key"/foo/bar"doc["foo"]["bar"]
Array index"/foo/0"doc["foo"][0]
Array append marker"/foo/-"Position after the last element (insert-only)
Escaped / in key"/a~1b"doc["a/b"]
Escaped ~ in key"/m~0n"doc["m~n"]

Escape order matters when serializing a key: encode ~ as ~0 first, then encode / as ~1. Reversing the order produces ambiguous pointers.

JSON Patch (RFC 6902) operations

JSON Patch is a delta format: an array of operations that transforms one JSON document into another. It is the on-the-wire equivalent of what Diffpad shows in the diff result table.

OperationRequired fieldsEffect
addpath, valueInsert value at path; for arrays, insert before the index
removepathDelete the value at path
replacepath, valueEquivalent to remove + add at the same path
movepath, fromRemove from from, add at path
copypath, fromAdd a copy of the value at from to path
testpath, valueAssert the value at path equals value; abort the patch if not

A JSON Patch matching the kind of Kubernetes change developers compare daily:

[
  { "op": "remove",  "path": "/metadata/labels/tier" },
  { "op": "replace", "path": "/spec/replicas", "value": 4 },
  { "op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "nginx:1.26" },
  { "op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/cpu", "value": "500m" },
  { "op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/memory", "value": "512Mi" },
  { "op": "add",     "path": "/spec/template/spec/containers/0/env/-", "value": { "name": "CDN_URL", "value": "https://cdn.example.com" } }
]

The patch is replayable. Sending it to a server that supports Content-Type: application/json-patch+json applies the changes atomically; an error on any operation rolls back the prior ones in compliant implementations.

JSON Merge Patch (RFC 7396) syntax

JSON Merge Patch is the lighter alternative to JSON Patch. The patch document looks like the target document with only the changed fields, using null to indicate deletion.

SourcePatchResult
{"a":1, "b":2}{"b":3}{"a":1, "b":3}
{"a":1, "b":2}{"b":null}{"a":1}
{"a":1, "b":{"c":2}}{"b":{"c":3}}{"a":1, "b":{"c":3}}
{"a":[1,2,3]}{"a":[9]}{"a":[9]} (whole array replaced)
{"a":1}{"b":2}{"a":1, "b":2}

Arrays are always replaced wholesale. If the diff needs to add a single element to an array of fifty, JSON Patch is the right format; Merge Patch will rewrite the array. The HTTP PATCH method with Content-Type: application/merge-patch+json is the common transport.

YAML 1.1 vs YAML 1.2 type coercion

YAML 1.1 implementations (libyaml, PyYAML in default mode) coerce a long list of unquoted scalars to booleans and numbers. YAML 1.2 narrows the list to the JSON-compatible core schema. When diffing two YAML documents from different parsers, type coercion mismatches produce phantom diffs that disappear once both sides quote the same values.

Unquoted tokenYAML 1.1 typeYAML 1.2 type
true, falsebooleanboolean
yes, no, on, offbooleanstring
True, Falsebooleanboolean
Yes, No, YES, NObooleanstring
null, Null, NULL, ~nullnull
0o17, 0xffinteger (octal/hex)integer (1.2 mandates 0o prefix for octal)
0123integer 83 (1.1, octal)integer 123 (decimal; leading zero is decorative)
01:23:45integer 5025 (sexagesimal)string "01:23:45"

The classic case is country: NO in a Norway-specific config. YAML 1.1 reads NO as the boolean false; YAML 1.2 reads it as the string "NO". Quoting unambiguous values is the safest workaround when round-tripping between parsers.

Command-line equivalents

The web interface is one of several ways to produce a structural diff. The shell tools below produce equivalent output for batch comparisons or CI pipelines.

TaskCommand
Semantic JSON diff with sorted keysdiff <(jq -S . a.json) <(jq -S . b.json)
Print a JSON Patch from A to Bnpx json-diff-patch a.json b.json
Semantic YAML diff (mikefarah yq)diff <(yq -S 'sort_keys(..)' a.yaml) <(yq -S 'sort_keys(..)' b.yaml)
Cross-format YAML/JSONdiff <(yq -P -o=json a.yaml | jq -S .) <(jq -S . b.json)
Key-only diff (ignore values)diff <(jq -S 'paths' a.json) <(jq -S 'paths' b.json)
Apply a Merge Patchjq -s '.[0] * .[1]' a.json patch.json
Apply a JSON Patchnode -e 'const p=require("fast-json-patch"); console.log(JSON.stringify(p.applyPatch(...).newDocument))'
List paths to all scalarsjq -c 'paths(scalars)' a.json

The jq -S flag sorts object keys recursively, which removes the most common source of cosmetic line-noise in a textual diff.

Common diff failure modes

When a structural diff returns surprising output, the cause is almost always one of these. Symptom on the left, root cause and fix on the right.

SymptomCauseFix
Phantom diff on 1.0 vs 1.00Serializers normalize trailing zeros differentlyCompare parsed values, not re-serialized strings
Phantom diff "yes" vs yesYAML 1.1 coerces unquoted yes to boolean; quoted stays stringPin the parser to YAML 1.2, or quote ambiguous scalars consistently
Whole array marked replaced when one element changedSequence diff uses positional comparisonDiff array elements by an identity key (Kubernetes uses name; OpenAPI uses operationId)
Key reorder shown as deletion + insertionObject key order treated as semanticSwitch the tool's comparison mode from textual to structural
Cross-format diff loses a YAML anchorAnchor expanded before comparison; JSON has no anchor conceptCompare YAML-to-YAML, or accept that anchor semantics do not survive the JSON round-trip
Comment-only change is missedComments are stripped before structural comparisonUse a text-mode diff for documentation review; comments are not part of the parsed tree
Floating-point fields show rounding errorParser converts 0.1 + 0.2 to 0.30000000000000004Round to a fixed precision before comparison, or store as string
Large integer fields lose precisionJavaScript JSON.parse uses Number (53-bit precision)Use a BigInt-aware parser; Postgres BIGINT IDs over 2^53 silently corrupt in JS clients
Timestamp shows diff but renders identicalDifferent ISO 8601 forms of the same instant (2026-01-01T00:00:00Z vs 2026-01-01T00:00:00+00:00)Parse to a canonical form (epoch milliseconds) before comparison
Diff flags null vs missing keyThese are not equivalent: explicit null records intent, missing key records absencePick one convention per schema; some APIs require explicit nulls for deletion

Related concepts

JSON Schema vs JSON Patch.
Schema describes shape; Patch describes change. A patch is replayable against any document that the source schema accepts.
Three-way merge.
When two parties edit the same document independently, a three-way merge needs a common ancestor plus both deltas. JSON Patch does not encode three-way merge semantics; tools like kpatch and kustomize add that layer for Kubernetes.
Conflict-free replicated data types (CRDTs).
Data structures that converge automatically under concurrent edits. CRDTs replace diff-and-patch for collaborative editing in tools like Figma and Linear.
Operational transformation (OT).
The pre-CRDT approach to concurrent editing, still in use at Google Docs. OT requires a central server to sequence operations; CRDTs do not.
kubectl diff.
Reads live cluster state and produces a YAML-aware diff against a local manifest. Internally uses the same library family that powers structural YAML comparisons in browser tools.