Skip to content

Instantly share code, notes, and snippets.

@oscherler
Last active April 6, 2023 10:03
Show Gist options
  • Save oscherler/22eb60eb78a4e4e89e0506578e8b820a to your computer and use it in GitHub Desktop.
Save oscherler/22eb60eb78a4e4e89e0506578e8b820a to your computer and use it in GitHub Desktop.
Diff JSON in Git using gron

jsondiff: diff JSON in Git using gron

gron is an incredible tool that makes JSON greppable. But it also makes it diffable, which is great if you have JSON files in Git.

To use gron to diff JSON in Git, save the json-diff script below and make it executable. Then add a difftool as shown in gitconfig, and optionally create an alias to invoke it more easily. Then try it:

git init
echo '{"foo":42,"bar":"hello"}' > foo.json
git add foo.json && git commit -m 'Initial commit.'
echo '{"foo":43,"bar":"hello"}' > foo.json
git jdiff

will give you:

--- a/foo.json
+++ b/foo.json
@@ -1,3 +1,3 @@
 json = {};
 json.bar = "hello";
-json.foo = 42;
+json.foo = 43;
[difftool "jsondiff"]
cmd = "/path/to/json-diff $LOCAL $REMOTE"
[alias]
jdiff = difftool -t jsondiff -y
#!/bin/zsh
# gron: https://github.com/tomnomnom/gron
GRON=/usr/local/bin/gron
DIFF=/usr/bin/diff
# colordiff: https://www.colordiff.org
COLORDIFF=/usr/bin/colordiff
# use colordiff in interactive mode, diff otherwise
if [ -t 1 ]
then
DIFFER=${COLORDIFF}
else
DIFFER=${DIFF}
fi
LOCAL="$1"
REMOTE="$2"
"${DIFFER}" -u --label "a/$REMOTE" --label "b/$REMOTE" <( "$GRON" < "$LOCAL" ) <( "$GRON" < "$REMOTE" ) | less
@mjaggard
Copy link

less at end of json-diff should be less -R otherwise you lose the colour.

Also, this could do with a way of passing non-JSON files to your normal diff tool.

@oscherler
Copy link
Author

You’re absolutely right. I have the -R in my LESS environment variable*, so I didn’t even realise it.

I didn’t understand the second part of your comment, though.

* I did export LESS='--RAW-CONTROL-CHARS --ignore-case --no-init --line-numbers'. --RAW-CONTROL-CHARS is -R, --ignore-case means I can do a case insensitive search by using a lowercase search string, but it becomes case sensitive if there are uppercase characters in it, --no-init does not clear the screen on quitting, I prefer it that way, and --line-numbers makes it faster on large files, if I remember right.

@mjaggard
Copy link

Thanks. Regarding the second comment - at the moment when I run this I get an error on all my files apart from JSON ones. It would be nice if the normal diff process worked for those and I only see the JSON diff for JSON files.

@oscherler
Copy link
Author

Right. I used to only call it on single files: git jdiff foo.json.

Maybe you can do it with .gitattributes, as mentioned here: https://stackoverflow.com/a/52820305

@mjaggard
Copy link

I'll give it a go. Thanks

@CholoTook
Copy link

Thanks for this, exactly what I was looking for!

@lukestanley
Copy link

Is this the most simple way to use gron for diffing JSON in git?
On Ubuntu and I was able to apt install gron and add a .gitattributes with this:
*.json diff=gron

and add to .git/config:
[diff "gron"]
textconv=gron

then I think git diff could be used with it. Not sure if I missed a step. Does this help?

@oscherler
Copy link
Author

@lukestanley Seems legit, and very simple indeed. My solution is based on writing json-diff first, and only later thinking of using it with git, so that’s why it’s probably more complicated than needed. Thanks for the heads up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment