How can I convert my JSON to CSV using jq?

前端 未结 5 1630
礼貌的吻别
礼貌的吻别 2020-12-28 17:25

I have the following JSON data:

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


        
相关标签:
5条回答
  • 2020-12-28 17:34

    Using Perl and its JSON module:

    #!/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 讨论(0)
  • 2020-12-28 17:34

    Using perl wasn't a good solution for me but after a bit of trial and error I figured out you can do it with just jq using the join() operator.

    First make an array of the output you need, then join the array elements using commas.

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

    Enjoy. :)

    0 讨论(0)
  • 2020-12-28 17:39

    Building upon Joe Harris' answer, you can use the @csv filter so that strings are properly quoted and escaped when necessary :

    jq -r '[.case, .custom."speech invoked", .custom."input method"] | @csv'
    
    0 讨论(0)
  • 2020-12-28 17:52

    Here is another solution. If data.json contains the sample data then

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

    will produce

    id,case,speech invoked,input method,session ID
    111,Y,no,hard,420
    
    0 讨论(0)
  • 2020-12-28 17:56

    Using jq, you can use this filter:

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

    Just note that written this way, the "custom" properties will always be written in the end, no matter what order the properties are in.

    0 讨论(0)
提交回复
热议问题