Diff two modified JSON files in fish
Another interesting command line JSON exercise: you have two JSON files, you want to diff a modified version of one to the other, and your shell is fish.
For making JSON diffable, gron is a great choice: it transforms a JSON file into a list of assignment lines. Like this:
$ echo '{"a": ["b", "c"]}' | gron
json = {};
json.a = [];
json.a[0] = "b";
json.a[1] = "c";
gron doesn't help us with modifications, so jq is again a good choice there. In my case, I had one file that contained an array of objects, and wanted to compare the first element of that array to the content of a second file. Additionally I wanted to set the value of one key of the object from the first file to null
. With jq that's quick work:
jq '.[0] | .large_field = null' file1.json | gron
The second file I wanted as-is, and that's just
gron file2.json
The last problem I wanted to solve was how to actually get the output from those two commands to diff (or colordiff). I could just pipe them to files and compare those, but that's untidy. As usual it's much easier to find answers to this for bash than for fish. In bash (and zsh, and ksh) it looks like this:
colordiff -u <(jq '.[0] | .large_field = null' file1.json | gron) <(gron file2.json)
A quick peek at the bash manual page reveals that <(
is used for "process substitution". Search the web and you'll find that in fish that's accomplished with the magic command psub:
colordiff -u (jq '.[0] | .large_field = null' file1.json | gron | psub) (gron file2.json | psub)
And that's it. Pretty colored diff of the parts you're interested in, and no temporary files to remove afterwards.