web-dev-qa-db-ja.com

jqを使用してJSONをCSVに変換するにはどうすればよいですか?

次のJSONデータがあります。

{"id":"111","case":"Y","custom":{"speech invoked":"no","input method":"hard","session ID":"420"}}

jq を使用してCSV形式に変換するにはどうすればよいですか?結果は次のようになりますか?

id,case,session Id,speech invoked,input method

111,Y,420,no,hard

私は以下を試しましたが、うまくいきませんでした:

{(.id),(.case),(.custom."session Id"),(.custom."speech invoked"),(.custom."input method")}

不可能な場合は、PerlまたはShellソリューションを使用してください。

17
user2711819

PerlとそのJSONモジュールの使用:

#!/usr/bin/Perl
use warnings;
use strict;
use feature qw{ say };

use JSON;

my $input = << '__JSON__';
{"id":"111","case":"Y","custom":{"speech invoked":"no","input method":"hard","session ID":"420"}}
__JSON__

my $struct = decode_json($input);

my @header = grep ! ref $struct->{$_}, keys %$struct;
Push @header, map keys %{ $struct->{$_} },
              grep ref $struct->{$_},
              keys %$struct;

my @row = grep ! ref, values %$struct;
Push @row, map values %$_, grep ref, values %$struct;

say join ',', @header;
say join ',', @row;
0
choroba

Joe Harrisの回答に基づいて、@ csvフィルターを使用して、文字列が適切に引用符で囲まれ、必要に応じてエスケープできるようにします。

jq -r '[.case, .custom."speech invoked", .custom."input method"] | @csv'
22
Olivier Aubert

Perlを使用することは私にとって良い解決策ではありませんでしたが、少し試行錯誤した結果、join()演算子を使用してjqだけでそれを実行できることがわかりました。

最初に必要な出力の配列を作成し、次にコンマを使用して配列要素を結合します。

jq -r '[.case, .custom."speech invoked", .custom."input method"] | join(", ")'

楽しい。 :)

18
Joe Harris

Jqを使用すると、次のフィルターを使用できます。

with_entries(select(.key != "custom")) + .custom
    | to_entries
    | map(.key), map(.value)
    | @csv

この方法で記述されていることに注意してください。「カスタム」プロパティは、プロパティの順序に関係なく、常に最後に書き込まれます。

11
Jeff Mercado

これが別の解決策です。 data.jsonにはサンプルデータが含まれています

jq -M -s -r 'map(.+.custom|del(.custom)) | (.[0]|keys_unsorted), (.[]|[.[]]) | join(",")' data.json

生成されます

id,case,speech invoked,input method,session ID
111,Y,no,hard,420
1
jq170727