LoginSignup
3
1

More than 1 year has passed since last update.

jdでJSONのdiffを手軽に抽出

Posted at

TL; DR

  • jd を使えば、2つのJSONの差分をフィールド単位で取得できる!
$ cat a.json
{"foo": {"bar": 1, "baz": 2}}
$ cat b.json
{"foo": {"bar": 1, "baz": 3}}

$ jd a.json b.json
@ ["foo","baz"]
- 2
+ 3

はじめに

更新処理前後の差分等、2つの以上のJSONファイルを見比べる際に、diff コマンドを使うことがあると思います。

しかし、diff コマンドは差分が行単位でしか出ないため、 jq で整形してもフィールド名しか出てこず「結局差分はどこで起きているんだ?」と探し回る必要があります。

bazフィールドってどこにあるの?
$ diff <(cat a.json | jq) <(cat b.json | jq)
4c4
<     "baz": 2
---
>     "baz": 3

そこで今回は、JSONの構造に基づいて差分を出してくれる jd コマンドを紹介したいと思います。

バージョン

$ jd -version
jd version 1.6.1

使い方

引数の渡し方は diff と同じです。差分をフィールドのフルパスで出してくれるので、変更箇所が一目瞭然です

$ cat a.json
{"foo": {"bar": 1, "baz": 2}}

$ cat b.json
{"foo": {"bar": 1, "baz": 3}}

# 差分表示、@行がフィールドのフルパス
$ jd a.json b.json
@ ["foo","baz"]
- 2
+ 3

配列の場合はインデックスで表されます(jqのパス表現と同じ)。

$ cat a.json
{"foo": ["a", "b", {"c": 1}]}
$ cat b.json
{"foo": ["a", "b", {"c": 2}]}
$ jd a.json b.json
@ ["foo",2,"c"]
- 1
+ 2

$ cat a.json
{"foo": ["a", "b", {"c": 1}]}
$ cat c.json
{"foo": ["a", "b"]}
$ jd a.json c.json
@ ["foo",2]
- {"c":1}

-color で差分に色を付けられます。差分が多いときは色がある方が見やすいですね。

image.png

YAMLの差分も表示可能

さらに、JSONだけでなくYAMLにも対応しています。マニフェストの変更点を確認するのに便利そうです。

$ cat a.yaml
foo:
  bar: 1
  baz: 2
$ cat b.yaml
foo:
  bar: 1
  baz: 3
$ jd -yaml a.yaml b.yaml
@ ["foo","baz"]
- 2
+ 3

ファイルのパッチ

2つのJSONの差分表示だけでなく、JSONに差分を適用して変更することも可能です。
JSON間の差分を記録して、別のJSONに適用することもできます。

$ cat a.json
{"foo": {"bar": 1, "baz": 2}}
$ echo diff.patch
diff.patch
$ jd -p diff.patch a.json
{"foo":{"bar":2,"baz":2}}

ただし、diffの元となる値が食い違うとエラーが発生するので注意が必要です1

$ cat a.json
{"foo": {"bar": 1, "baz": 2}}
$ cat diff.patch
@ ["foo", "bar"]
- 4
+ 2
$ jd -p diff.patch a.json
2022/09/10 10:23:33 found 1 at [foo bar]: expected 4

おわりに

以上、jd でJSONのdiffを取得する方法の紹介でした。
ちょうど痒い所に手が届くので、jqyq にならんでこのツールには今後たくさんお世話になると思います。

  1. 差分適用という意味では安全な機構だと思います。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1