Bir deri bir kemik
jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv'
veya:
jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @csv'
Ayrıntılar
Bir yana
Ayrıntıları açıklamak zordur çünkü jq akışa yöneliktir, yani tek bir değer yerine bir JSON verisi dizisi üzerinde çalışır. Girdi JSON akışı, filtrelerden geçirilen ve daha sonra programın sonunda bir çıktı akışında kodlanan bazı dahili türe dönüştürülür. Dahili tür JSON tarafından modellenmez ve adlandırılmış bir tür olarak mevcut değildir. Çıplak dizinin ( .[]
) veya virgül operatörünün çıktısını inceleyerek en kolay şekilde gösterilebilir (bunu doğrudan incelemek bir hata ayıklayıcı ile yapılabilir, ancak bu JSON'un arkasındaki kavramsal veri türleri yerine jq'nin dahili veri türleri açısından olacaktır) .
$ jq -c '. []' <<< '["a", "b"]'
"a"
"b"
$ jq -cn '"a", "b"'
"a"
"b"
Çıktının bir dizi olmadığını unutmayın (ki bu olabilir ["a", "b"]
). Kompakt çıktı ( -c
seçenek), her bir dizi öğesinin (veya ,
filtreye ilişkin bağımsız değişkenin ) çıktıda ayrı bir nesne haline geldiğini (her birinin ayrı bir satırda olduğunu) gösterir.
Akış, JSON dizisine benzer , ancak kodlandığında çıktı ayırıcı olarak RS yerine satırsonu satırları kullanır . Sonuç olarak, bu dahili tip, bu cevapta "dizi" jenerik terimiyle anılır ve "akış", kodlanmış girdi ve çıktı için ayrılmıştır.
Filtrenin Oluşturulması
İlk nesnenin anahtarları şu şekilde çıkarılabilir:
.[0] | keys_unsorted
Anahtarlar genellikle orijinal sıralarında tutulur, ancak tam sıranın korunması garanti edilmez. Sonuç olarak, değerleri aynı sırayla almak için nesneleri indekslemek için kullanılmaları gerekecektir. Bu ayrıca, bazı nesnelerin farklı bir anahtar sırasına sahip olması durumunda değerlerin yanlış sütunlarda olmasını önleyecektir.
Hem anahtarları ilk satır olarak çıkarmak hem de indeksleme için kullanılabilir hale getirmek için, bunlar bir değişkende saklanır. Ardışık düzenin bir sonraki aşaması daha sonra bu değişkene başvurur ve başlığı çıkış akışının başına eklemek için virgül operatörünü kullanır.
(.[0] | keys_unsorted) as $keys | $keys, ...
Virgülden sonraki ifade biraz karmaşıktır. Bir nesne üzerindeki dizin operatörü, "name", "value"
bu dizeler için bir özellik değerleri dizisi döndürerek bir dizi dizeyi alabilir (örneğin ). $keys
bir dizi değil, bir dizidir, dolayısıyla []
onu bir diziye dönüştürmek için uygulanır,
$keys[]
daha sonra aktarılabilir .[]
.[ $keys[] ]
Bu da bir dizi üretir, dolayısıyla dizi yapıcısı onu bir diziye dönüştürmek için kullanılır.
[.[ $keys[] ]]
Bu ifade, tek bir nesneye uygulanacaktır. map()
bunu dış dizideki tüm nesnelere uygulamak için kullanılır:
map([.[ $keys[] ]])
Son olarak, bu aşama için bu, bir diziye dönüştürülür, böylece her öğe çıktıda ayrı bir satır olur.
map([.[ $keys[] ]])[]
Neden diziyi map
sadece dışarıda dağıtmak için bir dizi içinde paketleyelim ? map
bir dizi üretir; .[ $keys[] ]
bir dizi üretir. Dizisine uygulamak map
, .[ $keys[] ]
bir dizi değer dizisi üretir, ancak diziler JSON türü olmadığından, bunun yerine tüm değerleri içeren düzleştirilmiş bir dizi elde edersiniz.
["NSW","AU","state","New South Wales","AB","CA","province","Alberta","ABD","GB","council area","Aberdeenshire","AK","US","state","Alaska"]
Her bir nesneden gelen değerlerin ayrı tutulması gerekir, böylece nihai çıktıda ayrı satırlar haline gelirler.
Son olarak, dizi @csv
formatlayıcıdan geçirilir .
Alternatif
Öğeler erken değil geç ayrılabilir. Bir dizi elde etmek için virgül operatörünü kullanmak yerine (bir diziyi doğru işlenen olarak iletmek), başlık dizisi ( $keys
) bir diziye sarılabilir ve +
değerler dizisini eklemek için kullanılabilir. Bunun yine de aktarılmadan önce bir diziye dönüştürülmesi gerekiyor @csv
.
json2csv
, stackoverflow.com/questions/57242240/…