【问题标题】:How can I convert my JSON to CSV using jq?如何使用 jq 将我的 JSON 转换为 CSV?
【发布时间】:2014-10-22 21:15:33
【问题描述】:

我有以下 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 解决方案。

【问题讨论】:

    标签: json perl shell csv jq


    【解决方案1】:

    使用 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;
    

    【讨论】:

    • 我仍然想使用 Text::CSV_XS 来创建输出,以防某些数据包括空格、引号、逗号等。
    • @Tanktalus:当然。只需调整最后两行。
    • 这不像问题所问的那样使用jq
    • 不知道为什么这个解决方案被否决。 jq 绝对比 Perl 更受欢迎,但问题是 any perl or shell solution is appreciated.
    【解决方案2】:

    使用 perl 对我来说不是一个好的解决方案,但经过一些试验和错误后,我发现您可以使用 join() 运算符仅使用 jq 来做到这一点。

    首先制作一个包含所需输出的数组,然后使用逗号连接数组元素。

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

    享受。 :)

    【讨论】:

    • 我离开了.custom."session ID",这样人们无需滚动就可以看到join()
    【解决方案3】:

    使用 jq,你可以使用这个过滤器:

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

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

    【讨论】:

    • 这很酷,因为它会在事先不知道键的情况下自动获取键并输出列标题。但问题是标题对于每一行都是 repeated 的。如果您有可变输入,您可以安全地只输出值,但如果输入是可变的,您将需要标题。首先将输入和输出标头仅存储到您的文件中,然后在第二遍中附加值。不过会阻止将输出通过管道传输到 gzip。
    【解决方案4】:

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

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

    【讨论】:

    • 看起来比连接好,但总是在值周围产生双引号。
    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      • 1970-01-01
      • 2018-08-20
      • 1970-01-01
      相关资源
      最近更新 更多