jqを使ってJSONをCSVに変換するいくつかの例。

最近、jqなる便利なツールを発見した。sedawkっぽい記法で、JSON文字列を整形したりフィルタできたりいろんなことができるようだ。
このjqを使って、JSON文字列をCSVに変換するいくつかの例を挙げる。JSON形式の文字列を返すAPIの試験結果をCSVに変換して、それをExcelに貼り付けるときなどに便利だろう。
なお、jqのインストールは、Macであれば

brew install jq

で行える。

単純なJSON形式

以下のJSONがあったとする。

{
  "name": "織田信長",
  "age": "49"
}

これをCSV形式に変換するには、以下のコマンドを実行すれば良い。

echo '{ "name": "織田信長", "age": "49" }' | jq -r '["name","age"], (. | [.name,.age]) | @csv'

結果は以下のとおり。

"name","age"
"織田信長","49"

配列になっているJSON形式

続いては配列になっているJSON形式の場合。以下のJSONがあったとする。

[
  {
    "name": "織田信長",
    "age": "47"
  },
  {
    "name": "豊臣秀吉",
    "age": "62"
  },
  {
    "name": "徳川家康",
    "age": "73"
  }
]

これをCSV形式に変換するには、以下のコマンドを実行すれば良い。

echo '[ { "name": "織田信長", "age": "47" }, { "name": "豊臣秀吉", "age": "62" }, { "name": "徳川家康", "age": "73" } ]' | jq -r '["name","age"], (.[] | [.name,.age]) | @csv'

結果は以下のとおり。

"name","age"
"織田信長","47"
"豊臣秀吉","62"
"徳川家康","73"

要素のひとつが配列になっているJSON形式

最後は、要素のひとつが配列になっているJSON形式の場合。以下のJSONがあったとする。

[
  {
    "name": "織田信長",
    "age": "47",
    "children": [
      {
        "name": "織田信忠",
        "rank": "1"
      },
      {
        "name": "織田信雄",
        "rank": "2"
      },
      {
        "name": "織田信孝",
        "rank": "3"
      }
    ]
  },
  {
    "name": "豊臣秀吉",
    "age": "62",
    "children": [
      {
        "name": "豊臣秀次",
        "rank": "1"
      },
      {
        "name": "豊臣捨松",
        "rank": "2"
      },
      {
        "name": "豊臣秀頼",
        "rank": "3"
      }
    ]
  },
  {
    "name": "徳川家康",
    "age": "73",
    "children": [
      {
        "name": "松平信康",
        "rank": "1"
      },
      {
        "name": "結城秀康",
        "rank": "2"
      },
      {
        "name": "徳川秀忠",
        "rank": "3"
      }
    ]
  }
]

これをCSV形式に変換するには、以下のコマンドを実行すれば良い。

echo '[ { "name": "織田信長", "age": "47", "children": [ { "name": "織田信忠", "rank": "1" }, { "name": "織田信雄", "rank": "2" }, { "name": "織田信孝", "rank": "3" } ] }, { "name": "豊臣秀吉", "age": "62", "children": [ { "name": "豊臣秀次", "rank": "1" }, { "name": "豊臣捨松", "rank": "2" }, { "name": "豊臣秀頼", "rank": "3" } ] }, { "name": "徳川家康", "age": "73", "children": [ { "name": "松平信康", "rank": "1" }, { "name": "結城秀康", "rank": "2" }, { "name": "徳川秀忠", "rank": "3" } ] } ]' | jq -r '["name","age","c
hildren_name","children_rank"], (.[] | {name,age,children:.children[]} | [.name,.age,.children.name,.children.rank]) | @csv'

結果は以下のとおり。

"name","age","children_name","children_rank"
"織田信長","47","織田信忠","1"
"織田信長","47","織田信雄","2"
"織田信長","47","織田信孝","3"
"豊臣秀吉","62","豊臣秀次","1"
"豊臣秀吉","62","豊臣捨松","2"
"豊臣秀吉","62","豊臣秀頼","3"
"徳川家康","73","松平信康","1"
"徳川家康","73","結城秀康","2"
"徳川家康","73","徳川秀忠","3"

さいごに

jq自体の説明やサンプルなどは、他のサイトで取り上げられているので割愛した。本記事では、現実的にありえそうな構造のJSONを使ったサンプルのみ取り上げた*1

*1:自分がAPIの結果をCSVにするとき、配列になっているJSONの取り扱いに苦労したので・・・