Reputation: 960
I have the following JSON data:
{"id":"111","case":"Y","custom":{"speech invoked":"no","input method":"hard","session ID":"420"}}
How can I convert it to CSV format using jq so my result looks like this?
id,case,session Id,speech invoked,input method
111,Y,420,no,hard
I tried the following, but it didn't work:
{(.id),(.case),(.custom."session Id"),(.custom."speech invoked"),(.custom."input method")}
If not possible any perl or shell solution is appreciated.
Upvotes: 18
Views: 16450
Reputation: 14695
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
Upvotes: 1
Reputation: 335
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'
Upvotes: 22
Reputation: 134511
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.
Upvotes: 12
Reputation: 14035
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. :)
Upvotes: 18
Reputation: 241988
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;
Upvotes: 0