web-dev-qa-db-fra.com

Comment puis-je convertir mon JSON au format CSV en utilisant jq?

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.

16
user2711819

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;
0
choroba

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'
21
Olivier Aubert

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. :)

18
Joe Harris

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.

11
Jeff Mercado

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
1
jq170727