2013-11-24 12 views
18

sto cercando di convertire un oggetto che assomiglia a questo:Come associare un oggetto ad array in modo che possa essere convertito in csv?

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

in formato CSV che assomiglia a questo:

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

io preferirei utilizzare lo strumento da riga di comando jq, ma non ci riesco sembra capire come fare il compito. Sono riuscito a ottenere le chiavi con jq '. | keys' test.json ma non sono riuscito a capire cosa fare dopo.

Il problema è che non è possibile convertire un oggetto k: v come questo direttamente in CSV con @csv. Deve essere una matrice, quindi dobbiamo prima convertire in un array. Se le chiavi fossero nominate, sarebbe semplice ma sono dinamiche quindi non è così facile.

+0

Perché non solo gsub ':' per ''? –

+0

google 'JSON a csv' ... un sacco di risultati – charlietfl

+0

hanno trovato questo in 15 secondi nella casella di ricerca nella parte superiore della pagina ... http: //stackoverflow.com/questions/8847766/how-to-convert-json-to- csv-format-and-store-in-a-variable/8924856 # 8924856 – charlietfl

risposta

25

Prova questo filtro:

to_entries[] | [.key, .value] 
  • to_entries converte un oggetto in un array di oggetti chiave/valore. [] interrompe l'array per ciascuno degli elementi nell'array
  • quindi per ciascuno degli elementi, nascosto a un array contenente la chiave e il valore.

Questo produce il seguente output:

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

quindi è possibile utilizzare il filtro @csv per convertire i file CSV alle righe.

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

Hmm. Per me questo restituisce "' \ "123 \", \ "abc \" "' ecc. I.e. ogni riga è inoltre quotata. –

+3

Assicurati di aggiungere il flag '-r' alla chiamata. Ti consigliamo di ottenere l'output non elaborato. –

+0

Grazie, l'avevo trascurato. –

1

Jeff risposta è un buon punto di partenza, qualcosa di più vicino a quello che ci si aspetta:

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

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

Ma non ha trovato un modo per unirsi con a capo:

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

"123,abc\n231,dbh\n452,xyz" 
+0

"\ n" è la rappresentazione JSON di newline; per vederlo come una nuova riga letterale, usa l'opzione -r command-lline di jq. Tuttavia, in generale, usare '@ csv' per ottenere CSV è il modo migliore per fare come @csv produce realmente CSV valido. – peak

3

Ecco un esempio Ho finito per utilizzare questa mattina (elaborazione degli avvisi 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") ' 

Questo discariche di un documento CVS separati che assomiglia a: "[Triggered] Something annoyingly frequent",31 "[Triggered] Even more frequent alert!",35 "[No data] Stats Server is probably acting up",55

-3
onecol2txt() { 
awk 'BEGIN { RS="_end_"; FS="\n"} 
    { for (i=2; i <= NF; i++){ 
     printf "%s ",$i 
     } 
    printf "\n" 
    }' 
} 
cat jsonfile | jq -r -c '....,"_end_"' | onecol2txt