複数のjsonファイルをjqを使ってmergeする

2017.06.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

自己紹介記事を除いて初投稿です!

全国のjqファンの皆様こんにちは。tjinjinです。

業務中に複数のJSONファイルをjq使ってmergeしたいなーと思ってたらなんとかできたので共有します!結構基本的な話だと思います。

動作環境

  • OSX 10.12.5
  • jq 1.5

テストデータを用意する

まず、簡単なテストデータを用意します。

$ cat hoge.json
{
  "hoge1": {
    "aaa": {
      "user": "user_aaa",
      "password": "pass_hoge1aaa"
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  }
}
$ cat fuga.json
{
  "fuga1": {
    "aaa": {
      "user": "user_aaa",
      "password": "pass_fuga1aaa"
    }
  },
  "fuga2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_fuga2bbb"
    }
  }
}

これらを使っていろいろ試してみましょう。

2つのファイルをmergeする

別の名前空間の2つのファイルを単純にmergeしたい場合は add を利用することでまとめることができます。

$ jq -s add hoge.json fuga.json
{
  "hoge1": {
    "aaa": {
      "user": "user_aaa",
      "password": "pass_hoge1aaa"
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  },
  "fuga1": {
    "aaa": {
      "user": "user_aaa",
      "password": "pass_fuga1aaa"
    }
  },
  "fuga2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_fuga2bbb"
    }
  }
}

要素を追加する

別の名前空間であれば問題ないのですが、新しい要素を追加したいようなケースではうまくいきません。

# 挿入したいデータ
$ cat hoge_add.json
{
  "hoge1": {
    "aaa": {
      "endpoint": "endpoint_hoge1_aaa"
    }
  }
}
$ jq -s add hoge.json hoge_add.json
{
  "hoge1": {
    "aaa": {
      "endpoint": "endpoint_hoge1_aaa"
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  }
}

上記の方法では要素が上書きされてしまいました。今回やりたかったことを整理すると、下記のようなファイルになることを想定していました。

{
  "hoge1": {
    "aaa": {
      "user": "user_aaa",
      "password": "pass_hoge1aaa",
      "endpoint": "endpoint_hoge1_aaa" # 重複しないデータが挿入される
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  }
}

* を使う

上記ケースでは * を使うと掛け合わせができます。

$ jq -s '.[0] * .[1]' hoge.json hoge_add.json
{
  "hoge1": {
    "aaa": {
      "user": "user_aaa",
      "password": "pass_hoge1aaa",
      "endpoint": "endpoint_hoge1_aaa"
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  }
}

.hoge1.aaa.endpoint が挿入されています。

データが重複するケース

データが重複するケースについても調べてみます。

$ cat hoge_add_duplicate.json
{
  "hoge1": {
    "aaa": {
      "password": "password",
      "endpoint": "endpoint_hoge1_aaa"
    }
  }
}
$ jq -s '.[0] * .[1]' hoge.json hoge_add_duplicate.json
{
  "hoge1": {
    "aaa": {
      "user": "user_aaa",
      "password": "password",
      "endpoint": "endpoint_hoge1_aaa"
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  }
}

$ jq -s '.[0] * .[1]' hoge_add_duplicate.json hoge.json
{
  "hoge1": {
    "aaa": {
      "password": "pass_hoge1aaa",
      "endpoint": "endpoint_hoge1_aaa",
      "user": "user_aaa"
    }
  },
  "hoge2": {
    "bbb": {
      "user": "user_bbb",
      "password": "pass_hoge2bbb"
    }
  }
}

要素が重複する場合はあと勝ちのようですね。

まとめ

jqはよく使うので、もうちょっと極めていきたいなーと思いました。まずはドキュメントをしっかり読みます。

参考