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,