arrayを含んだ順序が不揃いなJSONのdiff
arrayを含んだ順序が不揃いなJSONのdiffを取るのはだるい。だるい。
arrayを含んだJSON
arrayを含んだJSONというのはこういうやつです。
people0.json
[ { "name": "foo", "age": 10 }, { "name": "bar", "age": 20 } ]
people2.json
[ { "name": "bar", "age": 20 }, { "name": "foo", "age": 10 } ]
JSONを含んだJSON(unordered)のdiffを取りたい
jqの場合
jqにはkeyでソートする -S
というオプションはあるのだけれど。これではarrayはソートされない。
$ diff -u <(jq -S . people0.json) -u <(jq -S . people1.json) --- /dev/fd/63 2017-06-10 15:57:53.000000000 +0900 +++ /dev/fd/62 2017-06-10 15:57:53.000000000 +0900 @@ -1,10 +1,10 @@ [ { - "age": 10, - "name": "foo" - }, - { "age": 20, "name": "bar" + }, + { + "age": 10, + "name": "foo" } ]
これではダメ。まじめに構造を把握していれば、その構造の知識を使ってソートすることは可能(例えば今回の例ではname及びageでソートする)。
$ diff -u <(jq -S "sort_by(.name)" people0.json) <(jq -S "sort_by(.name)" people1.json)
これはOK。ただし、データに対する知識が要求される。
dictknife
だるかったので、dictknifeの --normalize
オプションではこれを良い感じでソートしてdiffが出ないようにした。
$ dictknife diff --normalize people0.json people1.json
もちろん、何か変更があればdiffが出る。
$ dictknife diff --normalize people0.json people2.json --- people0.json +++ people2.json @@ -1,10 +1,11 @@ [ { - "age": 10, + "age": 11, "name": "foo" }, { "age": 20, - "name": "bar" + "name": "bar", + "nickname": "big b" } ]
もう少し複雑なネストした形状
もう少しネストした複雑な形状のものもある。
例えばこういう(今度はYAML)
people3.yaml
- name: foo age: 10 parents: - name: A age: 40 - name: B age: 44 - name: bar age: 20 parents: - name: B age: 44 - name: A age: 40
people4.yaml
- name: bar age: 20 parents: - name: B age: 44 - name: A age: 40 - name: foo age: 10 parents: - name: A age: 40 - name: B age: 44
ネストしていても大丈夫。
$ dictknife diff --normalize people3.yaml people4.yaml $ dictknife diff --normalize people3.yaml people5.yaml --- people3.yaml +++ people5.yaml @@ -6,6 +6,10 @@ { "age": 40, "name": "A" + }, + { + "age": 42, + "name": "C" }, { "age": 44,