🗒️

jq コマンドで JSON を CSV に変換する

2024/08/26に公開

前置き

まとまった JSON データはあるが欲しいデータをお手軽に取り出したいとき、jq を使うと JSON に対してクエリをかける形で値を取り出せる。もっと欲を出して、出力結果を CSV にしてやりたいこともある。これも jq の範囲で対応可能である。

要約

以下のいずれかで良い。基本的には前者で問題なく、クォーテーションを省きたい場合は後者を使う(ただし注意点あり)。

  • cat test.json | jq -r '["uuid", "ipv4"], (.[] | [.uuid, .ipv4]) | @csv'
  • echo uuid,ipv4 && cat test.json | jq -r '.[] | "\(.uuid),\(.ipv4)"'

サンプルデータ

[
    {
        "uuid": "3861facf-939a-42ee-bb7d-3acf16deec22",
        "ipv4": "155.31.192.229"
    },
    {
        "uuid": "17cb6f50-69a9-4f89-803d-f8d08cb71ab0",
        "ipv4": "252.7.186.75"
    },
    {
        "uuid": "b09a19aa-3306-41dc-a76a-b305e763010a",
        "ipv4": "5.203.192.193"
    },
    {
        "uuid": "3cc3d20c-8b01-428c-8ead-7398aab3a55d",
        "ipv4": "79.52.14.188"
    },
    {
        "uuid": "90617d94-9cd5-4c01-9b39-1e8340afa046",
        "ipv4": "0.198.93.99"
    }
]

1. @csv オペレータを使う

確実かつ簡単。ただし jq の式はちょっとテクニカルになる。要領は次の通り。

  1. 見出し行を出力するために、見出し行を表現した配列と JSON を変換した配列を結合させる
  2. jq で一旦 JSON の各要素を配列に加工したうえで、@csv を配列に適用させる
cat test.json | jq -r '["uuid", "ipv4"], (.[] | [.uuid, .ipv4]) | @csv'
uuid,ipv4
"3861facf-939a-42ee-bb7d-3acf16deec22","155.31.192.229"
"17cb6f50-69a9-4f89-803d-f8d08cb71ab0","252.7.186.75"
"b09a19aa-3306-41dc-a76a-b305e763010a","5.203.192.193"
"3cc3d20c-8b01-428c-8ead-7398aab3a55d","79.52.14.188"
"90617d94-9cd5-4c01-9b39-1e8340afa046","0.198.93.99"

2. 手前味噌でフォーマットする

見た目だけだと @csv を使うよりは直感的かもしれない。
この方法では jq が JSON をフォーマットした形で出力できることを利用して、CSVっぽくする。副作用的になるが、この場合だと各値が " で囲わられなくなる。

ただし問題もあり、例えば「素直な」JSON なら大丈夫だが JSON の値に変な文字(特にカンマ)が含まれていると CSV が壊れる。上述のサンプルみたいに出力形式が固まっているものだけをターゲットにするなら問題ない。

(2) の場合、見出し行の処理は jq ではなく echo で代理し、jq の式も少しいじることになる。

echo uuid,ipv4 && cat test.json | jq -r '.[] | "\(.uuid),\(.ipv4)"'
uuid,ipv4
3861facf-939a-42ee-bb7d-3acf16deec22,155.31.192.229
17cb6f50-69a9-4f89-803d-f8d08cb71ab0,252.7.186.75
b09a19aa-3306-41dc-a76a-b305e763010a,5.203.192.193
3cc3d20c-8b01-428c-8ead-7398aab3a55d,79.52.14.188
90617d94-9cd5-4c01-9b39-1e8340afa046,0.198.93.99

Discussion