Si Kurus
jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv'
atau:
jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @csv'
Rinciannya
Ke samping
Mendeskripsikan detailnya rumit karena jq berorientasi pada aliran, artinya ia beroperasi pada urutan data JSON, bukan pada satu nilai. Aliran JSON masukan diubah menjadi beberapa jenis internal yang dilewatkan melalui filter, kemudian dikodekan dalam aliran keluaran di akhir program. Tipe internal tidak dimodelkan oleh JSON, dan tidak ada sebagai tipe bernama. Ini paling mudah ditunjukkan dengan memeriksa output dari indeks telanjang ( .[]
) atau operator koma (memeriksanya secara langsung dapat dilakukan dengan debugger, tetapi itu akan menjadi dalam hal tipe data internal jq, daripada tipe data konseptual di belakang JSON) .
$ jq -c '. []' <<< '["a", "b"]'
"Sebuah"
"b"
$ jq -cn '"a", "b"'
"Sebuah"
"b"
Perhatikan bahwa outputnya bukan array (yang akan menjadi ["a", "b"]
). Output ringkas ( -c
opsi) menunjukkan bahwa setiap elemen array (atau argumen ke ,
filter) menjadi objek terpisah dalam output (masing-masing berada pada baris terpisah).
Aliran seperti JSON-seq , tetapi menggunakan baris baru daripada RS sebagai pemisah keluaran saat dienkode. Akibatnya, tipe internal ini dirujuk oleh istilah umum "urutan" dalam jawaban ini, dengan "aliran" dicadangkan untuk masukan dan keluaran yang dikodekan.
Membangun Filter
Kunci objek pertama dapat diekstraksi dengan:
.[0] | keys_unsorted
Biasanya kunci akan disimpan dalam urutan aslinya, tetapi urutan yang tepat tidak dijamin. Akibatnya, mereka perlu digunakan untuk mengindeks objek untuk mendapatkan nilai dalam urutan yang sama. Ini juga akan mencegah nilai berada di kolom yang salah jika beberapa objek memiliki urutan kunci yang berbeda.
Untuk mengeluarkan kedua kunci sebagai baris pertama dan membuatnya tersedia untuk pengindeksan, mereka disimpan dalam variabel. Tahap berikutnya dari pipeline kemudian mereferensikan variabel ini dan menggunakan operator koma untuk menambahkan header ke aliran keluaran.
(.[0] | keys_unsorted) as $keys | $keys, ...
Ekspresi setelah koma sedikit terlibat. Operator indeks pada suatu objek dapat mengambil urutan string (misalnya "name", "value"
), mengembalikan urutan nilai properti untuk string tersebut. $keys
adalah array, bukan urutan, jadi []
diterapkan untuk mengubahnya menjadi urutan,
$keys[]
yang kemudian dapat diteruskan ke .[]
.[ $keys[] ]
Ini juga menghasilkan urutan, sehingga konstruktor array digunakan untuk mengubahnya menjadi array.
[.[ $keys[] ]]
Ekspresi ini akan diterapkan ke satu objek. map()
digunakan untuk menerapkannya ke semua objek dalam larik terluar:
map([.[ $keys[] ]])
Terakhir untuk tahap ini, ini diubah menjadi urutan sehingga setiap item menjadi baris terpisah di keluaran.
map([.[ $keys[] ]])[]
Mengapa menggabungkan urutan menjadi array di dalam map
satu - satunya untuk memisahkannya di luar? map
menghasilkan sebuah array; .[ $keys[] ]
menghasilkan urutan. Menerapkan map
urutan dari .[ $keys[] ]
akan menghasilkan larik urutan nilai, tetapi karena urutan bukan tipe JSON, jadi Anda mendapatkan larik pipih yang berisi semua nilai.
["NSW","AU","state","New South Wales","AB","CA","province","Alberta","ABD","GB","council area","Aberdeenshire","AK","US","state","Alaska"]
Nilai dari setiap objek harus dipisahkan, sehingga menjadi baris terpisah pada hasil akhir.
Akhirnya, urutan dilewatkan melalui @csv
pemformat.
Bergantian
Item dapat dipisahkan terlambat, bukan lebih awal. Alih-alih menggunakan operator koma untuk mendapatkan urutan (meneruskan urutan sebagai operan kanan), urutan header ( $keys
) bisa dibungkus dalam array, dan +
digunakan untuk menambahkan array nilai. Ini masih perlu diubah menjadi urutan sebelum diteruskan ke @csv
.
json2csv
ada di stackoverflow.com/questions/57242240/…