J'ai les données JSON suivantes:
{"id":"111","case":"Y","custom":{"speech invoked":"no","input method":"hard","session ID":"420"}}
Comment puis-je le convertir au format CSV en utilisant jq afin que mon résultat ressemble à ceci?
id,case,session Id,speech invoked,input method
111,Y,420,no,hard
J'ai essayé ce qui suit, mais cela n'a pas fonctionné:
{(.id),(.case),(.custom."session Id"),(.custom."speech invoked"),(.custom."input method")}
Si ce n'est pas possible, toute solution Perl ou Shell est appréciée.
Utilisation de Perl et de son module 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;
En vous appuyant sur la réponse de Joe Harris, vous pouvez utiliser le filtre @csv pour que les chaînes soient correctement citées et échappées lorsque cela est nécessaire:
jq -r '[.case, .custom."speech invoked", .custom."input method"] | @csv'
Utiliser Perl n’était pas une bonne solution pour moi, mais après quelques essais et erreurs, j’ai compris que vous pouviez le faire avec juste jq
en utilisant l’opérateur join()
.
Commencez par créer un tableau de la sortie dont vous avez besoin, puis joignez les éléments du tableau en utilisant des virgules.
jq -r '[.case, .custom."speech invoked", .custom."input method"] | join(", ")'
Prendre plaisir. :)
En utilisant jq, vous pouvez utiliser ce filtre:
with_entries(select(.key != "custom")) + .custom
| to_entries
| map(.key), map(.value)
| @csv
Notez simplement qu’écrites de cette façon, les propriétés "personnalisées" seront toujours écrites à la fin, quel que soit l’ordre dans lequel elles se trouvent.
Voici une autre solution. Si data.json
contient les exemples de données, alors
jq -M -s -r 'map(.+.custom|del(.custom)) | (.[0]|keys_unsorted), (.[]|[.[]]) | join(",")' data.json
produira
id,case,speech invoked,input method,session ID
111,Y,no,hard,420