Как конвертировать JSON в CSV с помощью jq?

У меня есть следующие данные JSON:

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

Как я могу преобразовать его в формат CSV с помощью jq, поэтому мой результат выглядит так?

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 или оболочки.

Ответы

Ответ 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;

Ответ 2

Использование perl не было хорошим решением для меня, но после небольшого количества проб и ошибок я понял, что вы можете сделать это всего лишь с помощью jq с помощью оператора join().

Сначала создайте массив требуемого результата, затем присоедините элементы массива с помощью запятых.

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

Enjoy.:)

Ответ 3

Основываясь на ответе Джо Харриса, вы можете использовать фильтр @csv, чтобы строки были правильно процитированы и экранированы при необходимости:

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

Ответ 4

Используя jq, вы можете использовать этот фильтр:

with_entries(select(.key != "custom")) + .custom
    | to_entries
    | map(.key), map(.value)
    | @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