JSON Semantic Diff

16 Nov 2025 in TIL

Spruce is a general purpose YAML & JSON merging tool, and one of it's subcommands is a semantic JSON diff. It captures added and removed fields, and highlights any type changes.

Installing Spruce

Spruce is written in Go, and can be installed in many different ways:

  1. With mise (which I highly recommend):

    bash
    mise use -g github:geofffranks/spruce
  2. With brew if you're on MacOS

    bash
    brew install starkandwayne/cf/spruce
  3. With go get:

    bash
    go get github.com/geofffranks/spruce

Example usage

Here are two sample JSON files. Between the first and the second, I've changed a value, changed two data types, and removed two fields:

json
{
"name": "Alice",
"age": "30",
"pets": "Fido",
"favourite_cake": "Carrot cake",
"another": {
"value": "here"
}
}
json
{
"name": "Alice Smith",
"age": 30,
"pets": ["Fido"],
"another": {}
}

If we run spruce diff, this information is returned to us in a format that makes is very easy to see the diffs:

diff
$ spruce diff first.json second.json
(root level)
- one map entry removed:
favourite_cake: "Carrot cake"
age
± type change from string to int
- 30
+ 30
another
- one map entry removed:
value: here
name
± value change
- Alice
+ Alice Smith
pets
± type change from string to list
- Fido
+ - Fido