json diffを効率よく、ワンライナーで

エキサイト株式会社 メディア事業部エンジニアの中です。

今回はjson diffを簡単にできる方法を記載しようと思います。

例えば、以下のようなjsonが2種類あったとします。

{
  "userId": 1,
  "id": 1,
  "title": "naka",
  "body": "sho"
}
{
  "body": "sho"
  "title": "naka",
  "id": 1,
  "userId": 1,
}

ただのdiff コマンドだと、以下のように、順番違うので差分が出てきてしまいます。

diff a.json b.json
2,3c2
< "userId": 1,
< "id": 1,
---
> "body": "sho",
5c4,5
< "body": "sho"
---
> "id": 1,
> "userId": 1

そこで、jq sort-keysでkeyで並び替えて比較すると綺麗に差分を比較することができます。

jqについては以下の公式を参考にしてください。

jq

diff <(jq --sort-keys . a.json) <(jq --sort-keys . b.json)

API通しの比較であれば、curlコマンドを中に入れ込めば、いちいちjsonファイルを作らなくても比較ができます。 新旧APIの比較などに使えそうですね。

差分がない場合

diff <(curl -s 'https://jsonplaceholder.typicode.com/posts/1' | jq --sort-keys) <(curl -s 'https://jsonplaceholder.typicode.com/posts/1' | jq --sort-keys)

差分がある場合

$ diff <(curl -s 'https://jsonplaceholder.typicode.com/posts/1' | jq --sort-keys) <(curl -s 'https://jsonplaceholder.typicode.com/posts/2' | jq --sort-keys)
2,4c2,4
<   "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
<   "id": 1,
<   "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
---
>   "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
>   "id": 2,
>   "title": "qui est esse",

差分がない場合は何も表示されないので簡単ですね。 差分がある場合は、どのキーなのかがわかるためすぐに調査できると思います。 vimdiffを使えば、差分のある文字列がどこなのかを特定しやすいので参考に使ってください。

$ vimdiff <(curl -s 'https://jsonplaceholder.typicode.com/posts/1' | jq --sort-keys) <(curl -s 'https://jsonplaceholder.typicode.com/posts/2' | jq --sort-keys)

f:id:excite-naka-sho:20210430184816p:plain