如何使用jq将JSON转换为CSV?

如何使用jq将JSON转换为CSV?,json,perl,shell,csv,jq,Json,Perl,Shell,Csv,Jq,我有以下JSON数据: {"id":"111","case":"Y","custom":{"speech invoked":"no","input method":"hard","session ID":"420"}} 如何使用将其转换为CSV格式,使结果如下所示 id,case,session Id,speech invoked,input method 111,Y,420,no,hard 我尝试了以下方法,但无效: {(.id),(.case),(.custom."session Id

我有以下JSON数据:

{"id":"111","case":"Y","custom":{"speech invoked":"no","input method":"hard","session ID":"420"}}
如何使用将其转换为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解决方案。

使用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;
#/usr/bin/perl
使用警告;
严格使用;
使用特征qw{say};
使用JSON;
my$input={$\uz},键%$struct;
推送@header,映射键%{$struct->{$},
grep ref$struct->{$},
密钥%$struct;
我的@row=grep!ref,值%$struct;
推送@row,映射值%$\u,grep ref,值%$struct;
说join',@header;
说join',@行;

使用perl对我来说不是一个好的解决方案,但是经过一点尝试和错误之后,我发现您可以使用
jq
使用
join()
操作符来完成

首先生成所需输出的数组,然后使用逗号连接数组元素

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

享受。:)

使用jq,您可以使用此过滤器:

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

请注意,以这种方式编写的“自定义”属性将始终在最后写入,无论属性的顺序如何。

根据Joe Harris的回答,您可以使用@csv过滤器,以便在必要时正确引用和转义字符串:

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

这是另一个解决方案。如果
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

我仍然希望使用Text::csvxs创建输出,以防某些数据包含空格、引号、逗号等内容。@Tanktalus:当然。只需调整最后两行。这不会像问题所问的那样使用
jq
。不知道为什么这个解决方案会被否决
jq
肯定比Perl更受欢迎,但问题是
任何Perl或shell解决方案都值得赞赏。
我停止了
.custom.“会话ID”
以便人们可以看到
join()
无需滚动。这很酷,因为它在不事先知道键的情况下自动获取键,并输出列标题。但问题是每行的标题都是重复的。如果您有变量输入,您可以安全地只输出值,但如果输入是变量,则需要标题。首先将输入和输出头隐藏到文件中,然后在第二次传递中附加值。将阻止将输出管道化到gzip。看起来比连接更好,但总是在值周围产生双引号。