Doğruluk, hız ve sadeliğe odaklanan bir jq klonu: Jaq
(github.com/01mf02)- jaq, JSON veri işleme aracı
jqnun bir klonudur; çoğu durumdajqile uyumluluğu korurken daha doğru ve öngörülebilir bir uygulama olmayı hedefler - Komut satırı programı
jaq,jqiçin bir drop-in replacement olarak kullanılabilir ve Rust kütüphanesijaq-core, Rust programları içinde jq programlarını derleyip çalıştırabilir jqda bulunmayan YAML, CBOR, TOML ve XML desteği sunar;jaq-coreçok iş parçacıklı ortamlarda güvenle kullanılabilir ve JSON ötesinde rastgele veri tiplerini destekler- Performans değerlendirmesinde
jaq-3.0, 31 benchmarkın 20'sinde en hızlıydı;jq-1.8.15'inde,gojq-0.12.18ise 6'sında en hızlıydı - Güvenlik açısından panic önleme, bellek güvenliği ve girdi verisiyle jq filtrelerinin I/O sınırlandırmasını garanti etmeye çalışır; ancak zaman, bellek ve stack gibi kaynak tükenmesi durumlarını ele almaz
jaq neler sunuyor
- jaq, JSON veri işleme aracı
jqiçin bir klondur; telaffuzu/ʒaːk/olup Jacques ile aynıdır jqda olmayan veri formatı desteği sunar-
YAML
-
CBOR
-
TOML
- XML
- Ayrı bir manual bulunur ve playground üzerinden denenebilir
- jaq iki biçimde sunulur
- Komut satırı programı
jaq:jqiçin drop-in replacement olarak kullanılabilir - Kütüphane
jaq-core: Rust programları içinde jq programlarını derleyip çalıştırabilir
-
Tasarım hedefleri
-
Doğruluk
- jaq, çoğu durumda
jqile uyumluluğu korurken daha doğru ve öngörülebilir bir jq uygulaması olmayı hedefler
- jaq, çoğu durumda
-
Performans
- jaq, başlangıçta
jq 1.6nın uzun açılış süresi rahatsız edici olduğu için geliştirildi; bu ortamda açılış süresi yaklaşık 50ms idi - Bu açılış süresi özellikle çok sayıda küçük dosya işlenirken belirgin hale gelir
jq 1.7ile açılış süresi büyük ölçüde iyileşti, ancak jaq birçok benchmarkta hâlâjqdan daha hızlıdır
- jaq, başlangıçta
-
Sadelik
- jaq, hata olasılığını azaltmak ve katkı sunmayı kolaylaştırmak için basit ve küçük bir uygulamayı hedefler
Kurulum ve derleme
- Linux, Mac ve Windows için ikili dosyalar releases page üzerinden indirilebilir
- macOS veya Linux'ta homebrew ile kurulabilir
brew install jaqbrew install --HEAD jaq
- Kaynaktan derlemek için Rust toolchain gerekir
cargo install --locked jaqcargo install --locked --git https://github.com/01mf02/jaq
- Depoyu klonladıysanız
cargo build --releaseveyacargo install --locked --path jaqile derleme ya da kurulum yapılabilir - jaq, Rust'ın desteklediği tüm sistemlerde çalışmalıdır; aksi halde issue açılması istenir
Performans değerlendirmesi
- Performans değerlendirmesi, jaq, jq ve gojq arasında yapılan çeşitli benchmarklardan oluşur
emptybenchmarkı, null girdiyleemptyfiltresininkez çalıştırarak açılış süresini ölçerbf-fibbenchmarkı, jq ile yazılmış bir Brainfuck yorumlayıcısında Fibonacci sayıları üreten bir Brainfuck betiğini çalıştırır- Benchmark verileri, Linux çalıştıran AMD Ryzen 5 5500U sisteminde üretildi
- Kullanılan komut:
bench.sh target/release/jaq jq-1.8.1 gojq-0.12.17 | tee bench.json - Tabloda
jaq-3.0,jq-1.8.1,gojq-0.12.18sonuçları milisaniye cinsinden gösterilir N/A, hata veya 10 saniyeyi aşma anlamına gelir
- Kullanılan komut:
- Sonuç özeti
jaq-3.0, 20 benchmarkta en hızlıydıjq-1.8.1, 5 benchmarkta en hızlıydıgojq-0.12.18, 6 benchmarkta en hızlıydı
gojq,tree-flattentestinde çok daha hızlıdır; çünküflattenfiltresini tanım olarak değil, native olarak uygular
Güvenlik modeli ve sınırlar
- jaq şunları garanti etmeye çalışır
- Kaynak tükenmesi vakaları dışında panic oluşmaması
- Belleğe zarar vermeyen bellek güvenliği
- jq filtresi çalıştırılmadan önce dosya okunması dışında, girdi verisi ve jq filtresinin I/O işlemi başlatamaması
- Bu garantilerin bozulduğu durumlar bug kabul edilir ve raporlanmalıdır
- jaq, hiçbir tür kaynak tükenmesi durumuna karşı önlem almaz
- Çalışma süresi sınırsız uzayabilir
- Bellek sınırsız kullanılabilir
- Stack alanı sınırsız kullanılabilir
- Örnek olarak, girdi verisi okunurken veya jq filtresi çalıştırılırken stack overflow oluşabilir
jaq -nr 'repeat("[")' | jaqjaq -n 'def f: 1+f; f'
Denetim ve testler
- jaq core, iki ayrı NLnet hibesi kapsamında Radically Open Security tarafından denetlendi
- İlk ve ikinci güvenlik denetimlerinde orta veya düşük önem derecesine sahip sorunlar bulundu
- Güvenlik denetimindeki tüm sorunlar giderildi ve
jaq-core/fuzziçine jaq için birden fazla fuzzing hedefi eklendi - jaq'ın JSON ayrıştırıcısı hifijson da zaten fuzzing hedeflerine sahipti
- jaq için 500'den fazla testten oluşan bir test paketi bulunur
Kullanıcı örnekleri
- Bir kullanıcı,
jaqınjqdesteğini doğrudan uygulamaktan çok daha faydalı olduğunu veValTtrait üzerinden sağlanan genişletilebilirlik sayesinde kendi tiplerine jq desteğini kolayca ekleyebildiğini söyledi - Başka bir kullanıcı, jaq kullanan Rust programının, Python'daki
jqPyPI crate'i ve tüm dosya üzerinde tek sorgu çalıştıran Python döngüsü bir kez işi bitirene kadar, tüm dosya üzerinde tüm sorguları üç kez çalıştırabildiğini belirtti wsjqyorumlayıcısı örneğinde, jaq'ın diğer jq uygulamalarından belirgin biçimde daha hızlı olduğu ve doğruluğa verdiği önemin etkileyici bulunduğu ifade edildi- İlgili
wsjqbenchmarkında jaq, jq'dan 5–10 kat, gojq'dan ise 15–196 kat daha hızlıydı
- İlgili
- certificate transparency log verilerini
certstream-serverile işleyen bir kullanıcı,jqpipe işlemede sorun yaşadığını; jaq'a geçtikten sonra daha hızlı açılış süresi sayesinde düşük özellikli bir VM'de bile akışı yakalayabildiğini söyledi
Fon desteği
- jaq projesi, NLnet tarafından kurulan NGI0 Entrust ve NGI0 Commons fonlarıyla destekleniyor
- Mali destek, European Commission'ın Next Generation Internet programı üzerinden sağlanıyor
- Ek fon desteği, Swiss State Secretariat for Education, Research and Innovation tarafından sağlanıyor
1 yorum
Hacker News yorumları
jq geliştirmenin 5 yıl durmuş olup ancak yakın zamanda yeniden canlandığı düşünülürse, bilinen hatalar da yeni hatalar da dahil, bu süre boyunca raporların birikmiş olması şaşırtıcı değil
Artık yeniden hız kazanıp uzun süredir biriken açık işleri yavaş yavaş temizleyecek gibi görünüyor
Benzer veya ilham alınmış projeleri, alternatif olmayan projelerle birlikte README'de tanıtma yaklaşımı hoşuma gidiyor
Bu projenin README'sinde https://github.com/yamafaktory/jql'yi öğrendim; uzun zamandır aradığım araç olduğu için memnunum
JAQ'yu kötülemek istemem ama JQ tarzı söz dizimi anlaması fazla zor olduğundan jql bana daha uygun geliyor
JSON'u anahtar-değer biçimindeki satırlara düzleştirerek
grepgibi basit akış işlemleriyle iyi uyumlu hale getiriyor: https://github.com/tomnomnom/gronAncak gerçekten SQL benzeri bir deneyim bekliyordum. Neden doğrudan SQL'i kopyalayıp
"SELECT * FROM $json WHERE x>1"gibi sorgulama imkânı vermediklerini anlamıyorumHerkes kod golfü yapar gibi kendi anlaşılması zor sembolik sorgu dilini yaratmak istiyor sanki. Aşırı kısa ama bariz olmayan eski Unix tarzı söz diziminden uzaklaşıp PowerShell yaklaşımına daha yakın olmasını isterdim
|={"b""d"=2, "c"}ifadesi jq'dakiselect(."b"."d" == 2 or ."c" != null)gibi bir anlama geliyor gibi; jq tarafı daha uzun olsa da daha açık hissettiriyorGerçekte
.[] | select(...)gerekir muhtemelen, ama jql'de de benzer bir varsayım olabilir; örneğin eksiksiz olup olmadığından emin olmadığım için sonuç açısından çok fark etmiyorKendisine uygulamak ya da “makrolar” kullanmak da mümkün görünüyor
jq'nun fikrini seviyorum ama sık kullanmadığım için istediğimi yapmak üzere her seferinde söz dizimini kılavuzdan aramam gerekiyor
Ne yazık ki jq ile yaptığım işlerin %99'u
| jq .Ayrı olarak bir yapılandırma dili oluşturmaya başlamıştım; meğer JSON sorguları için de epey iyiymiş: https://docs.ruuda.nl/rcl/rcl_query/
jq ile çözemediğim ama RCL ile çözebildiğim bir örnek burada: https://fosstodon.org/@ruuda/111120049523534027
Gerekli işi ve küçültülmüş bir örnek kaynak JSON'u birlikte verdiğinizde doğru jq betiğini üretiyor
Karmaşık gereksinimleri tek seferde doğru açıklamaktansa Copilot ile adım adım yineleyerek çözüme yönlendirmek daha kolay ve güvenilir. Yineleme sırasında başlangıçtakinden daha iyi fikirler de akla gelebiliyor
ChatGPT veya başka araçlar da benzer şekilde çalışır gibi
https://github.com/01mf02/jaq/blob/main/Cargo.lock
Bağımlılık sayısı epey fazla
Bağımlılık çok olunca zamanla birbirleriyle temelden uyumsuz hale gelme riski artıyor gibi görünüyor ve bakım büyük bir iş olacak gibi
Örneğin 2 yıl sonra da derlenir mi diye düşünüyorum
jq çok güçlü bir araç, ama son zamanlarda DuckDB de yaygın kullanılıyor
Veri bir ölçüde tablo biçimindeyse SQL çok daha doğal bir dil
C#’taki LINQ’ya biraz benziyor ama SQL daha standartlaşmış olduğu için daha çok hoşuma gidiyor
Dil içinde ham koleksiyonları SQL ile sorgulayabilmek harika olurdu; daha da ötesi koleksiyonları şeffaf biçimde Sqlite’a kaydedebilmek daha da iyi olurdu
Bir veritabanından vb. veri aldıktan sonra döngü ya da stream API ile basit işlem yapan kodları görünce hep eksik hissediyorum. Bu tür kullanımda SQL, Java/Kotlin/Python/JavaScript’ten çok daha üst düzey ve kısa
Ham JSON çıktısının tamamını bir sqlite tablosuna kaydediyor, orada sanal sütunlar oluşturuyor, ardından
selectsonucunu bir shell döngüsünden geçiriyorumİç içe döngüler açılıyor; doğru kaydı DB’de kontrol edip yeniden çalıştırabildiğim için hata ayıklanabilirlik çok daha iyi hale geliyor
Aslında yaptığım şeyin bir DAG olduğunu fark ettim ve her zaman başarıyla işlenen son kayıttan yeniden başlıyorum. Bunu ifade edecek
Makebenzeri bir araç var mı merak ediyorumMake’in SQL hedefi yok; Airflow gibi tam teşekküllü DAG işleyicileri ise shell parçalarını birleştirmek için fazla ağır
Yine de SQL’de özyinelemeli sorguları kısa ve öz ifade etmenin bir yolu hâlâ zor bulunuyor
https://github.com/dinedal/textql
Doğruluk açısından uint64 sayıların kesilmeden gösterilip gösterilemediğini merak ediyorum
Şu anda jq’da beni en çok rahatsız eden kısım bu
Ancak en yeni şartname olan RFC 8259’un yalnızca sayıların metin biçimini belirttiği, anlambilimi belirlemediği yönünde bir düzeltme var
Pratikte çoğu uygulama JSON’u JavaScript’in bir alt kümesi gibi ele aldığı için bu, sayıların 64 bit kayan nokta olduğu varsayımına yol açıyor
Ondalık sayı literalleri kullanarak hassasiyeti koruduğu, karşılaştırma işlemlerinin hassasiyete saygı duyduğu ama aritmetik işlemlerin kesilebileceği belirtiliyor
Şu anda decimal64’e kestiği için biraz kafa karıştırıcı; sonraki sürümde JSON şartnamesinin önerisine uygun olarak binary64(double) biçimine kesecek şekilde düzeltilecek: https://github.com/jqlang/jq/pull/2949
jless’e geçtikten sonra geriye bakmadım
Kullanıcı arayüzü diğerlerinden çok daha ileride
jq basit bir görüntüleyici değil, bir JSON sorgu dili işleyicisi
Rust’ın bir yerlerinde terminal çizgi sanatı kütüphanesi olması sevimli, ama jaq’ı çalıştırınca iTerm’e megabaytlarca escape code döktü ve sonunda iTerm bunu yazıcıya göndermeye çalıştı
Fazla akıllı davranmış
echo *json | rush -- jaq -rf ./this-program.jq {} | datamash ...gibi bir bağlamda TTY’ye sanatsal efektler koymaya çalışmanın uygun olmadığını düşünüyorumHatanın nedeni her hâlükârda
jaq’tastrftimeolmamasıydıİlk izlenimim, güzel hata mesajları olduğu ama
halt_error/0olmadığı yönündehalt_error’ı yorum satırına aldıktan sonra jq ve gojq’dan daha yavaştıAynı girdide
jqyaklaşık 0,023 saniye,gojqyaklaşık 0,070 saniye,jaqise yaklaşık 0,103 saniye sürdüKullanılan
aoc22-13.jqhttps://pastebin.com/raw/YiUjEu2n,input.txtise https://pastebin.com/raw/X0FSyTNfjq yerine yq kullanmaya başladım; önemli bir fark var mı merak ediyorum
Şahsen https://github.com/mikefarah/yq’yu https://github.com/kislyuk/yq’ya tercih ediyorum
YAML işlemenin JSON’dan çok daha zor olduğunu anlıyorum, ama yq sürüm 3’ten 4’e geçerken sözdizimini jq’ya daha yakın hale getirmiş olsa da bir şekilde tamamen aynı değil
Ayrıca yq’da if-then-else yok; bu da kötü tasarlanmış ya da atlanmış gibi görünüyor: https://github.com/mikefarah/yq/issues/95
YAML işlemek gerektiğinde yq iyi çalışıyor ve yorumları da oldukça iyi ele alıyor, ancak saf JSON işleme için jq daha iyi bir araç