jd: Diff and Patch JSON Structurally
jd compares two JSON documents structurally, so reordered keys and different indentation do not register as changes.
A line diff of JSON is noisy because key order and whitespace vary. jd compares the parsed structure, giving a meaningful diff and an optional patch you can apply.
What it does
jd parses both JSON files and diffs the resulting structures, reporting changes by JSON path rather than by line. Key order and formatting are ignored. With -o it writes a jd-format patch, and jd can later apply that patch with -p. Exit status is nonzero when the documents differ.
Common usage
jd a.json b.json
# treat arrays as unordered sets
jd -set a.json b.json
# emit a patch, then apply it later
jd -o diff.patch a.json b.json
jd -p diff.patch a.jsonOptions
| Flag | What it does |
|---|---|
| -set | Treat arrays as unordered sets |
| -mset | Treat arrays as multisets (order-independent, keep duplicates) |
| -o <file> | Write the diff as a jd-format patch |
| -p <file> | Apply a jd-format patch to the input |
| -f <format> | Output format: jd (default) or patch (RFC 6902) |
| -yaml | Read the inputs as YAML |
In CI
Use jd to gate on semantic JSON changes: jd committed.json generated.json exits nonzero only when the structure actually differs, so reformatting or key reordering will not fail the build. For API schemas or fixtures, this avoids the false positives a text diff would raise.
Common errors in CI
"invalid JSON" (or a parse error) means one input is not valid JSON, often a template that was not rendered. Unexpected diffs on arrays usually mean order matters by default; add -set or -mset if order should be ignored. "jd: command not found" means the Go binary is not installed on the runner.