Skip to content

Instantly share code, notes, and snippets.

@Checksum
Last active September 9, 2024 07:08
Show Gist options
  • Save Checksum/17c84306f563eca40b353f6ed83d0feb to your computer and use it in GitHub Desktop.
Save Checksum/17c84306f563eca40b353f6ed83d0feb to your computer and use it in GitHub Desktop.
JSON diff and patch for jq
# JSON diff and patch for jq (https://stedolan.github.io/jq/)
# Author: Srinath Sankar
#
# Usage:
# diff: jq -sS 'include "diff-patch"; diff' a.json b.json > patch.json
# patch: jq -sS 'include "diff-patch"; patch' a.json patch.json
#
# Caveats: tested only with top level objects using jq 1.6
def flatten_obj:
walk(if type == "array" then sort else . end)
| . as $obj
| reduce ($obj | paths(scalars)) as $path
( {};
.[$path | join("~>")] = ($obj | getpath($path))
);
def zip_obj:
. as $obj
| reduce (. | keys[]) as $key
( {};
. | setpath($key | split("~>") | map(. as $k | try tonumber catch $k); $obj[$key])
);
def diff:
(.[0] | flatten_obj) as $a
| (.[1] | flatten_obj) as $b
| ($a | keys) as $aKeys
| ($b | keys) as $bKeys
| ($aKeys - $bKeys) as $removed
| ($bKeys - $aKeys) as $added
# Modified
| reduce ($a | keys[]) as $key
( {};
. as $diff
| if $a[$key] != $b[$key] then
$diff[$key] |= $b[$key]
else
$diff
end
)
# Deleted
| reduce $removed[] as $k
( .;
.[$k] |= "~>-"
)
# Added
| reduce $added[] as $k
( .;
.[$k] |= $b[$k]
)
| zip_obj;
def patch:
(.[0] | flatten_obj) as $input
| (.[1] | flatten_obj) as $patch
| ($input * $patch)
| with_entries(select(.value != "~>-"))
| zip_obj;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment