Jq Paketi Kullanımı

Eğer JSON dosyaları ile uğraşıyorsanız, terminalden Jq eklentisi ise işlemlerinizi hızlandırabilirsiniz. Bir önceki yazımda Httpie paketini anlatmış ve Yazılımcı Curl’ü demiştim. Bu Jq paketini de httpie paket ile beraber kullanıcam. Çünkü uzak bir kaynaktaki json dosyası üzerinden işlem yapacağım, O yüzden ilk önce dilerseniz httpie paketini anlattığım yazımı inceleyin.

Jq paketinin detaylarına geçelim.

Kurulum

sudo apt-get install jq

komutu ile bilgisayarınıza kurabilirsiniz.

Basit Kullanımı

Bu eklentiyi jq komutu ile kullanacağız. Genel olarak kullanım amacım bir yerdeki json dosyasını işlemek (parse etmek) üzerine olacak.

http httpbin.org/get

Bu komut ile httpbin.org/get adresine bir istek atalım ve dönen cevabı inceleyelim.

{
    "args": {},
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
        "Host": "httpbin.org",
        "User-Agent": "HTTPie/0.9.2"
    },
    "origin": "73.192.158.136",
    "url": "http://httpbin.org/get"
}

Dönen cevap içinden sadece origin veya headers yazan alanı çekmek istiyorum.

Eğer origin alanını çekmek istersem

http httpbin.org/get | jq .origin

komutu ile gelen isteği jq ya atıyorum ve .origin ile sadece belirttiğim alanı getir diyorum. Aynı şekilde

http httpbin.org/get | jq .headers

ile sadece headers alanını çekebilirim.

Peki ikisini tek bir satırda yazarak çekebilir miyim?

http httpbin.org/get | jq '{headers,origin}'

Böyle de kullanarak ikisini tek seferde çekebilirsiniz. Tek tırnak içindeki alanlar Jq filtreleridir, yavaş yavaş ısınmaya başladık bu filtrelere.

Şuan küçük bir json ile çalışıyoruz, ne gerek var onu çekmeye diyebilirsiniz. Birazdan çok daha büyük json dosyaları ile çalışacağız.

Şimdi de kullanıcı ve şifre bilgilerini post eden bir HTTP isteği atalım.

http POST https://httpbin.org/post kullanici=sinan sifre=qwerty

Bu komut bana şunu dönecek.

{
    "args": {},
    "data": "{\"kullanici\": \"sinan\", \"sifre\": \"qwerty\"}",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "application/json",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
        "Content-Length": "41",
        "Content-Type": "application/json",
        "Host": "httpbin.org",
        "User-Agent": "HTTPie/0.9.2"
    },
    "json": {
        "kullanici": "sinan",
        "sifre": "qwerty"
    },
    "origin": "78.190.128.196",
    "url": "https://httpbin.org/post"
}

Ben de dönen data içinde json içindeki sifre değerine ulaşmak istiyorum, o zaman hemen bunu jq ya aktarıp alalım.

http POST https://httpbin.org/post kullanici=sinan sifre=qwerty | jq .json.sifre

Bu komut da bana qwerty değerini döner.Dönen json dosyasının içerisinde json diye bir alan var ve altında da kullanici ve sifre değerleri var, .json.sifre yazarak buraya ulaştım.

Şimdi biraz işleri karıştıralım. Mesela bir API üzerinden users endpointine istek attınız ve kullanıcıların json çıktısını aldınız. Bunun için ben örnek json olarak

https://jsonplaceholder.typicode.com/users

datasını kullanacağım. Bu json içinde 10 tane kullanıcının bilgileri var. Bu bilgileri jq ile işleyip almayı deneyelim.

Yukarıdaki bağlantı adresini tarayıcınızda açın, dikkat ederseniz tek bir bilgi içermiyor. Yani bir dizi (array) şeklinde birden fazla kullanıcının bilgisini tutuyor. Bu nedenle biz de jq ile işlerken buna dikkat edicez.

http https://jsonplaceholder.typicode.com/users | jq '.[] .name'

Burda gelen verinin bir array olduğunu .[] ile söyledik ve her bir değeri dön dedik, sonra da döndüğün değer içinden name alanlarını bize göster dedik. Bunları da tırnak içinde jq filtresi olarak yazdık.

"Leanne Graham"
"Ervin Howell"
"Clementine Bauch"
"Patricia Lebsack"
"Chelsey Dietrich"
"Mrs. Dennis Schulist"
"Kurtis Weissnat"
"Nicholas Runolfsdottir V"
"Glenna Reichert"
"Clementina DuBuque"

şeklinde verdi, peki siz istiyorsunuz ki ben sadece isim ve e-mail değerini alıp yeni bir obje yapayım. Tamam, hallederiz.

http https://jsonplaceholder.typicode.com/users | jq '.[] | {isim: .name, mail: .email}'

Burda ise yine .[] ile kaynağın bir array olduğunu söyledik ve her birini dön dedik, sonra da isim ve mail adında bir data oluştur ve içine, döndüğün kaynaktaki .name ve .email alanlarını koy dedik. Bunun çıktısı da

{
  "isim": "Leanne Graham",
  "mail": "[email protected]"
}
{
  "isim": "Ervin Howell",
  "mail": "[email protected]"
}

şeklinde oldu. Ben ilk iki hariç kalanını sildim o yüzden 2 tane görüyorsunuz.

indis & has & key

Peki sadece 5. kullanıcıyı almak istesem ne yapardım? Bunun indisinin 4 olduğunu biliyorum, çünkü programlama dillerinde indis 0’ dan başlıyor. O yüzden,

http https://jsonplaceholder.typicode.com/users | jq '.[4]'

ile indisi 4 olan yani 5. kullanıcıyı çekebildim.

Peki ben ilk 2 kullanıcıyı çekmek isteseydim?

http https://jsonplaceholder.typicode.com/users | jq '.[0:2]'

Böylede 0 indisinden başla 2’ye kadar (2 dahil değil) getir dedim. 0 ve 1 getirdi, bunlar da ilk 2 kullanıcılar zaten.

Obje içinde hangi anahtarlar var görmek isterseniz

http https://jsonplaceholder.typicode.com/users | jq '.[0] | keys'

gibi kullanabilirsiniz. Ben burda 0. indisin anahtarlarını görmek istediğimi söyledim.

[
  "address",
  "company",
  "email",
  "id",
  "name",
  "phone",
  "username",
  "website"
]

şeklinde geri döndü.

Dönen değer içinde email alanı var mı diye kontrol etmek istersek;

http https://jsonplaceholder.typicode.com/users | jq '.[0] | has("email")'

şeklinde has(email) kullanıyoruz.

Şimdide kaynaktaki adres bilgisi hariç diğerlerini alalım.

http https://jsonplaceholder.typicode.com/users | jq '.[0] | del(.address)'

Burda ise del(.address) ile, adres verisini silip ekrana bastırdım.

select & contains

Şimdide biraz koşullu arama yapalım.

http https://jsonplaceholder.typicode.com/users | jq '.[] | select(.id <3)'

Bunun için select değerini kullanıyoruz ve diyoruz ki .id değeri 3’den küçük olanları getir.

http https://jsonplaceholder.typicode.com/users | jq '.[] | select(.email == "[email protected]")'

Şimdi de .email değeri [email protected] olanı getir dedim.

http https://jsonplaceholder.typicode.com/users | jq '.[] .website | contains(".com")'

Her bir dönen değer içindeki .website değeri .com içeriyor mu diye sordum, bunun sonucu true veya false olarak döner.

strings & numbers & arrays

Bu 3 filtre de gelen veri içinde string olanı, number olanı veya array olanı ayırmak için kullanılır.

➜ http https://jsonplaceholder.typicode.com/users | jq '.[] .id | strings'  
➜ http https://jsonplaceholder.typicode.com/users | jq '.[] .id | numbers'
1
2
3
4
5
6
7
8
9
10

İlk yazdığım .id | strings değeri bir şey dönmedi çünkü id alanı içersinde string olan hiçbir veri yok. Sonra strings yerine numbers yazdığımda ise verileri alabildim. Aynı şekilde dönen veri içinden array olanları filtrelemek isterseniz | array yazabilirsiniz.

sqrt & tostring & tonumber & floor

Filtreler içinde kullanabileceğiniz sqrt değeri, dönen değerin karekökünü alır.

~ http https://jsonplaceholder.typicode.com/users | jq '.[8] | .id | sqrt'
3

Bu şekilde indisi 8 olan yani 9. elemanı çektik bunun id değeri 9 olduğunu biliyorum, bunu ver dedim sonra da bunu sqrt içerisine pipe ederek 3 değerini aldım. Gerçek hayatta nasıl bir ihtiyaç sonrasında bu özellik eklendi bilmiyorum.

Dikkat ettiyseniz 3 değeri sayı olarak döndü, bunu string yapmak için tostring kullanacağız, aynı komutun sonunda pipe ederek tostring ekleyelim.

~ http https://jsonplaceholder.typicode.com/users | jq '.[8] | .id | sqrt | tostring'
"3"

çıktı bu sefer 3 yerine “3” oldu, yani string haline geldi.

Şimdi de tam tersini yapalım, yani string değerini sayı haline getirelim.

~ http https://jsonplaceholder.typicode.com/users | jq '.[8] | .address.geo.lat'
"24.6463"

Burda .id değeri 9 olanın address > geo > lat değerini çektim bu da string olduğundan tırnak içerisinde “24.6463” döndü. Bunu sayı yapmak için | tonumber ekleyelim,

~ http https://jsonplaceholder.typicode.com/users | jq '.[8] | .address.geo.lat | tonumber'
24.6463

Bakın tırnaklardan kurtuldu, peki bunu noktalarından kurtarıp tam sayı yapalım mı? o zaman da floor kullanacağız.

~ http https://jsonplaceholder.typicode.com/users | jq '.[8] | .address.geo.lat | tonumber | floor'
24

Şimdi de dönen değer 24 oldu.