web-dev-qa-db-fra.com

Comment mapper un objet sur des tableaux afin qu'il puisse être converti en csv?

J'essaie de convertir un objet qui ressemble à ceci:

{
  "123" : "abc",
  "231" : "dbh",
  "452" : "xyz"
}

Pour CSV qui ressemble à ceci:

"123","abc"
"231","dbh"
"452","xyz"

Je préférerais utiliser l'outil de ligne de commande jq mais je n'arrive pas à comprendre comment faire l'affectation. J'ai réussi à obtenir les clés avec jq '. | keys' test.json mais je ne savais pas quoi faire ensuite.

Le problème est que vous ne pouvez pas convertir un objet k: v comme celui-ci directement en csv avec @csv. Il doit s'agir d'un tableau, nous devons donc d'abord convertir ce dernier en tableau. Si les clés étaient nommées, ce serait simple, mais elles sont dynamiques, donc ce n’est pas si facile.

24
Louis

Essayez ce filtre:

to_entries[] | [.key, .value]
  • to_entries convertit un objet en un tableau d'objets clé/valeur. [] divise le tableau en chacun des éléments du tableau
  • puis pour chacun des éléments, convertissez en un tableau contenant la clé et la valeur.

Cela produit la sortie suivante:

[
  "123",
  "abc"
],
[
  "231",
  "dbh"
],
[
  "452",
  "xyz"
]

Ensuite, vous pouvez utiliser le filtre @csv pour convertir les lignes en lignes CSV.

$ echo '{"123":"abc","231":"dbh","452":"xyz"}' | jq -r 'to_entries[] | [.key, .value] | @csv'
"123","abc"
"231","dbh"
"452","xyz"
35
Jeff Mercado

Voici un exemple que j'ai utilisé ce matin (traitement des alertes PagerDuty):

cat /tmp/summary.json | jq -r '
  .incidents
  | map({desc: .trigger_summary_data.description, id:.id})
  | group_by(.desc)
  | map(length as $len
  | {desc:.[0].desc, length: $len}) 
  | sort_by(.length) 
  | map([.desc, .length] | @csv)
  | join("\n") '

Cela vide un document séparé par CVS qui ressemble à quelque chose comme: "[Triggered] Something annoyingly frequent",31 "[Triggered] Even more frequent alert!",35 "[No data] Stats Server is probably acting up",55

4
Jón Tómas

La réponse de Jeff est un bon point de départ, quelque chose de plus proche de ce que vous attendez:

cat input.json | jq 'to_entries | map([.key, .value]|join(","))'

[
 "123,abc",
 "231,dbh",
 "452,xyz"
]

Mais n'a pas trouvé de moyen de rejoindre en utilisant newline:

cat input.json | jq 'to_entries | map([.key, .value]|join(","))|join("\n")'

"123,abc\n231,dbh\n452,xyz"
1
tomsoft

Essayez ceci Donnez le même résultat que vous voulez

echo '{"123":"abc","231":"dbh","452":"xyz"}' | jq -r 'to_entries | .[] | "\"" + .key + "\",\"" + (.value | tostring)+ "\""'
0
Sunil shakya