Skip to content
Bloga Dönün
Eğitimler

JSONPath Söz Dizimi Rehberi: Örneklerle JSON Sorgulama ve Filtreleme

JSONPath söz dizimini örneklerle öğrenin: kök, özyinelemeli iniş, joker karakterler, dilimler ve filtre ifadeleri. Her sorguyu tarayıcıda test edin.

11 dakika okuma

JSONPath söz dizimi rehberi: örneklerle JSON sorgulama ve filtreleme

JSONPath, JSON için bir sorgu dilidir; tıpkı XPath’in XML için bir sorgu dili olması gibi. Bir yol ifadesi yazarsınız ve değerlendirici eşleşen her değeri döndürür. Bir kitapçı belgesindeki tüm yazar adlarını almak için $.store.book[*].author yazarsınız ve yazar listesini geri alırsınız; tek satır gezinme kodu yazmanıza gerek kalmaz.

Bu rehber, JSONPath söz dizimindeki her seçiciyi okurken çalıştırabileceğiniz kopyala-yapıştır örneklerle adım adım anlatır. Baştan netleştirelim: iki lehçe var. 2007 Goessner lehçesi fiilî klasiktir, RFC 9535 ise Şubat 2024’te yayımlanan resmî IETF standardıdır. Ortak yollarda anlaşır, sınır durumlarında ayrışırlar; bu yüzden rehber, farkları ortaya çıktıkça işaret eder. Aşağıdaki her ifadeyi JSONPath Tester aracında deneyebilir ve karşılaştırmak için iki motor arasında geçiş yapabilirsiniz.

Başlangıç için seçici hızlı bakış tablosu burada. Yazının geri kalanı her satırı, ortak tek bir JSON belgesi üzerinde işlenmiş bir örnekle genişletir.

SeçiciAnlamıÖrnek
$Belgenin kökü$
@Geçerli öğe (filtrelerde)[?(@.price < 10)]
.name / ['name']Alt üye$.store.book
..Özyinelemeli iniş$..author
*Tüm öğeler / üyeler$.store.book[*]
[0]Dizi indeksi$.store.book[0]
[start:end:step]Dizi dilimi (yarı açık)$.store.book[0:2]
[a,b]Adların / indekslerin birleşimi$.store.book[0,2]
[?()]Filtre ifadesi$.store.book[?(@.price < 10)]
length() count() match() search() value()RFC 9535 fonksiyonları (yalnızca filtre)[?length(@.title) > 15]

JSONPath nedir?

JSONPath, bir JSON belgesinden düğüm seçmeye yarayan bildirimsel bir sorgu dilidir. Nesneleri ve dizileri dolaşan bir döngü yazmak yerine, istediğiniz konumu bir yolla tarif edersiniz ve değerlendirici eşleşen değerleri döndürür. Zihinsel model, XPath’in XML için verdiğiyle aynıdır: yapının içinde adım adım ilerleyen seçicilerden oluşan bir yol.

Geliştiricilerin JSON’a dokunduğu her yerde karşınıza çıkar. Bir API yanıtından alan çekmek, bir tümleştirme testinde bir değeri doğrulamak, Kubernetes, AWS Step Functions ve Azure Logic Apps için işlem hattı yapılandırmalarında alanlara erişmek ve gezinme mantığını elle yazmadan büyük ya da düzensiz JSON’dan veri ayıklamak için kullanırsınız.

Lehçe ayrımını açıkladığı için tarihçeye kısa bir not. Stefan Goessner JSONPath’i 2007’de önerdi. Hızla yayıldı ve fiilî standart hâline geldi, ama hiçbir zaman resmî olarak belirtilmedi; bu yüzden uygulamalar ayrıntılarda birbirinden uzaklaştı. IETF bu açığı Şubat 2024’te, ilk resmî JSONPath spesifikasyonu olan RFC 9535 ile kapattı. Her iki lehçe de bugün canlıdır; aynı ifadenin onu çalıştıran kitaplığa göre farklı davranabilmesinin nedeni budur.

Sorgulamaya başlamadan önce yapıyı okumak işe yarar. Dağınık girdiyi JSON Biçimlendirici ile güzel biçimlendirip iç içe geçmeyi görünür kılın.

Örnek belge

Aşağıdaki her örnek, klasik Goessner kitapçı JSON’u üzerinde çalışır. Bunu bir kez yapıştırın ve yeniden kullanın:

{
  "store": {
    "book": [
      { "title": "Sayings of the Century", "author": "Nigel Rees", "price": 8.95 },
      { "title": "Sword of Honour", "author": "Evelyn Waugh", "price": 12.99 },
      { "title": "Moby Dick", "author": "Herman Melville", "price": 8.99 },
      { "title": "The Lord of the Rings", "author": "J. R. R. Tolkien", "price": 22.99 }
    ],
    "bicycle": { "color": "red", "price": 19.95 }
  }
}

Başlık, yazar ve fiyatı olan dört kitap ve bir bisiklet. Şunu aklınızda tutun: fiyatlar 8.95, 12.99, 8.99 ve 22.99; ileride filtre sonuçlarını belirleyen şey bu.

Kök, alt ve özyinelemeli iniş ($ . ..)

Her ifade $ ile yazılan kökten başlar. Oradan alt öğelere bir noktayla ya da köşeli parantez gösterimiyle inersiniz; ikisi eşdeğerdir:

$.store.book          → the book array
$['store']['book']    → identical result

Bir anahtarda boşluk, nokta veya başka özel karakterler olduğunda ihtiyacınız olan şey köşeli parantez gösterimidir: $['first name'], $.first name ifadesinin işe yaramayacağı yerde çalışır.

.. işleci özyinelemeli iniştir. Yalnızca doğrudan alt öğeleri değil, belgenin her düzeyini arar ve sonraki seçiciyle herhangi bir derinlikte eşleşen her şeyi toplar:

$..author
→ ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]

.. mı yoksa tam yol mu kullanmalı

Özyinelemeli iniş kullanışlıdır ama körüdür. $..price, ağaçtaki her yerdeki her fiyatla eşleşir; bu, istemiyor olabileceğiniz store.bicycle.price dâhildir. Şekli bildiğinizde, sorgunun kesin kalması için yolu açıkça yazın:

$..price                  → [8.95, 12.99, 8.99, 22.99, 19.95]  (includes the bicycle)
$.store.book[*].price     → [8.95, 12.99, 8.99, 22.99]         (only books)

.. işlecini gerçekten düzensiz ya da bilinmeyen yapılar için saklayın. Takas, denetime karşı kolaylıktır: verinizi ne kadar iyi tanıyorsanız, açık bir yolu o kadar çok tercih etmelisiniz.

Joker karakterler, indeksler ve dizi dilimleri (* [0] [start:end:step])

Joker karakter *, bir dizinin tüm öğelerini ya da bir nesnenin tüm üyelerini seçer:

$.store.book[*].title
→ ["Sayings of the Century", "Sword of Honour", "Moby Dick", "The Lord of the Rings"]

Dizi indeksleri sıfır tabanlıdır ve negatif indeksler sondan sayar:

$.store.book[0].title     → ["Sayings of the Century"]
$.store.book[-1].title    → ["The Lord of the Rings"]

Dilimler, Python ve JavaScript ile aynı yarı açık [start:end:step] kuralını kullanır: start dâhildir, end hariç tutulur.

$.store.book[0:2].title   → ["Sayings of the Century", "Sword of Honour"]

Bu, üç değil iki kitap döndürür; indeks 0 ile indeks 1, indeks 2’den önce durarak. Hariç tutan üst sınır, en sık karşılaşılan JSONPath hatasıdır; bu yüzden aklınıza kazımaya değer:

[0:2]   → first TWO elements (indices 0, 1)   ← correct
[0:3]   → first THREE elements (indices 0, 1, 2)

Kenara kadar gitmek için bir sınırı atlayın, her N’inci öğe için de bir adım ekleyin:

$.store.book[2:].title    → ["Moby Dick", "The Lord of the Rings"]
$.store.book[:3].title    → first three titles
$.store.book[::2].title   → ["Sayings of the Century", "Moby Dick"]  (every other)

Filtre ifadeleri [?()]

Filtreler, JSONPath’i asıl işe yarar kılan yerdir. [?()] filtresi yalnızca yüklemin doğru olduğu öğeleri tutar ve filtrenin içinde @, test edilen geçerli öğeyi gösterir.

10’dan ucuz kitapları seçmek için:

$.store.book[?(@.price < 10)].title
→ ["Sayings of the Century", "Moby Dick"]

Kitapçı fiyatlarına (8.95, 12.99, 8.99, 22.99) karşı iki kitap uygun düşer. Filtre yüklemlerini adım adım şöyle kurarsınız:

  1. Bir değişmez değerle karşılaştırın. ==, !=, <, <=, >, >= kullanın; örneğin @.price > 10.
  2. Bir karakter dizisi eşleştirin. Karakter dizisi değişmezleri tek tırnak alır: @.author == 'Nigel Rees'.
  3. Varlığı sınayın. Çıplak bir üye başvurusu, o üyeyi içeren öğeleri seçer: [?(@.isbn)] yalnızca isbn içeren kitapları tutar.
  4. Koşulları birleştirin. Yüklemleri && ve || ile birleştirin: [?(@.price < 10 && @.author == 'Herman Melville')].

En sık yapılan filtre hatası, @ kapsamıdır. Yüklemin içinde geçerli öğe @’dir, $ değil. $.price yazmak, test edilen kitaba değil belge köküne işaret eder:

$.store.book[?($.price < 10)]   → wrong scope, matches nothing useful
$.store.book[?(@.price < 10)]   → correct: each book's own price

Filtrelerde RFC 9535 ile Klasik

İki lehçe, boşluk ve tırnak konusunda yollarını ayırır. Klasik hoşgörülüdür; boşluksuz [?(@.price<10)] sorunsuz ayrıştırılır. RFC 9535 ise dil bilgisini tam olarak izler ve filtrenin nasıl yazıldığı konusunda daha katıdır. Başka bir yerde çalışan bir filtre başarısız olursa, boşlukları ve motoru denetleyin. Filtreleri temiz tutun (boşluklu işleçler, tek tırnaklı karakter dizileri) ve hangi kitaplık sonunda çalıştırırsa çalıştırsın aynı biçimde değerlendirilsin.

Birleşim seçicileri: birden çok anahtarı tek seferde seçin ([a,b])

Bir birleşim seçicisi, tek bir parantez içinde birden çok ad veya indeks listeler ve hepsini toplar:

$.store.book[0]['title','author']
→ ["Sayings of the Century", "Nigel Rees"]

Birleşimler indekslerle de çalışır ve sabit bir izdüşüm için onları başka seçicilerle karıştırabilirsiniz:

$.store.book[0,2].title          → ["Sayings of the Century", "Moby Dick"]
$.store.book[*]['title','price']  → title and price of every book

Tüm bir nesne ya da bir joker karakter taraması yerine birkaç belirli alan istediğinizde doğru araç birleşimlerdir.

RFC 9535 fonksiyonları: length, count, match, search, value

RFC 9535, beş standart fonksiyon uzantısı tanımlar. Neredeyse herkesi tökezleten ve rakip rehberlerin sürekli yanlış yazdığı kural şudur:

Bu fonksiyonlar yalnızca bir filtre [?...] içinde çağrılabilir, hiçbir zaman bağımsız bir yol bölümü olarak değil.

$.store.book.length() yazmak geçerli RFC 9535 değildir ve standart dil bilgisi bunu reddeder. O bölüm-çağrısı biçimi, spesifikasyonun parçası değil, bir jsonpath-plus uzantısıdır. Uzunluğa göre filtrelemek için fonksiyonu yüklemin içinde çağırırsınız:

$.store.book[?length(@.title) > 15]
→ [
    { "title": "Sayings of the Century", "author": "Nigel Rees", "price": 8.95 },
    { "title": "The Lord of the Rings", "author": "J. R. R. Tolkien", "price": 22.99 }
  ]

Seçilen iki başlık da 15 karakterden uzun; “Moby Dick” (9) ile “Sword of Honour” (15, 15’ten fazla değil) hariç tutulur.

Her fonksiyonun bir filtre içinde yaptığı şey şudur:

  • length() — bir karakter dizisinin, dizinin ya da nesnenin uzunluğu: [?length(@.title) > 15]
  • count() — bir düğüm listesindeki düğüm sayısı: [?(count(@.authors) > 1)]
  • match() — tam karakter dizisi regex sınaması (I-Regexp deseni): [?match(@.author, 'J.*')]
  • search() — alt karakter dizisi regex sınaması: [?search(@.title, 'the')]
  • value() — tek düğümlü bir düğüm listesini karşılaştırma için değerine dönüştürür

Beşi de bir RFC 9535 özelliğidir. Klasik (Goessner) lehçesi bunları uygulamaz; bu yüzden fonksiyon tabanlı bir ifade başarısız olursa, onu bir filtre içinde çağırdığınızı ve motorunuzun RFC 9535’e ayarlı olduğunu doğrulayın.

RFC 9535 ile Klasik Goessner: aynı ifade neden farklı sonuç verir

Bir JSONPath ifadesi iki araçta farklı sonuçlar döndürdüğünde, sebebi genellikle lehçedir. İkisi şöyle karşılaştırılır:

YönKlasik Goessner (2007)RFC 9535 (2024)
StandartlaşmaFiilî, hiç resmileştirilmediİlk resmî IETF spesifikasyonu
Filtre boşluğu/tırnağıHoşgörülü ([?(@.price<10)] olur)Katı, dil bilgisini tam izler
Eksik üye karşılaştırmasıUygulamaya bağlıİyi tanımlı, hata fırlatmaz
Standart fonksiyonlarLehçenin parçası değillength count match search value
Normalleştirilmiş yollarKurallı biçim yokKurallı, tek tırnaklı parantez biçimi
Birleşim sıralamasıKitaplığa göre değişirBelirtilmiş

Pratik öneri: alt sisteminiz RFC 9535 uyumluluğunu duyuruyorsa, standart motora karşı yazıp doğrulayın. jsonpath.com, jsonpath-plus ya da Jayway tabanlı bir hizmetten kopyalanmış bir ifadeyi sürdürüyorsanız, sonuçlar yeniden üretilsin diye Klasik kullanın. JSONPath Tester iki motoru da tek bir geçişin arkasında çalıştırır; böylece bir ifadeyi bir kez yapıştırıp her lehçenin onu nasıl ele aldığını yan yana görebilirsiniz. O iki motorlu karşılaştırma, bir ayrışmayı tanılamanın en hızlı yoludur.

JSONPath ile XPath ile jq: hangisini kullanmalı

Bu üçü sık karıştırılır; işte kısa hâli:

  • JSONPath, JSON için bildirimsel bir yol sorgusudur. Kod yazmadan bir konumu adlandırmak istediğiniz yapılandırmalara ve test doğrulamalarına gömülmek için en iyisidir.
  • XPath, XML dünyasındaki karşılığıdır. JSONPath onun bazı gösterimlerini (*, .., []) ödünç almıştır; benzetme bu yüzden tutar, ama diller birbirinin yerine geçmez ve fonksiyon kümeleri farklıdır.
  • jq, komut satırı bir JSON işleyicisidir. Yol seçiminin çok ötesine geçer (dönüşüm, toplama, yeniden şekillendirme) ve kabuk işlem hattınızda yaşar.

Karar genellikle nettir. Gömülü bir doğrulama ya da bir işlem hattı yapılandırma alanı için JSONPath’e başvurun. Kabuk güdümlü dönüşüm ve veri düzenleme için jq’ya başvurun; jq Hızlı Başvuru Kılavuzu bu iş akışını derinlemesine ele alır. Soru, bir alanın nerede olduğu değil de bir payload’un beklenen bir şekle uyup uymadığıysa, onu JSON Şema Doğrulayıcı ve eksiksiz doğrulama kılavuzu ile doğrulayın.

7 yaygın JSONPath hatası

  1. Kök $’ı unutmak. store.book çoğu motor tarafından reddedilir; her ifade $ ile başlar.
  2. Dilimde bir-eksik hatası. [0:2] üç değil iki öğedir; üst sınır hariçtir.
  3. Yanlış lehçe. Bir Klasik ifadeyi RFC 9535 altında (ya da tersini) çalıştırmak, ayrıştırma hatası verebilir ya da farklı düğümlerle eşleşebilir. Motoru eşleşecek biçimde değiştirin.
  4. Fonksiyonu bağımsız bir bölüm olarak kullanmak. $.store.book.length() geçersiz RFC 9535’tir; length() fonksiyonunu bir filtre içinde çağırın.
  5. Bir filtrede @’ı unutmak. [?($.price < 10)] köke işaret eder; [?(@.price < 10)] kullanın.
  6. Yanlış parantez tırnağı. $[store] bir hatadır; anahtarı tırnaklayın: $['store'].
  7. .. ilk düzeyde durur sanmak. Özyinelemeli iniş yalnızca doğrudan alt öğelerde değil, her derinlikte eşleşir.

JSONPath’i çevrimiçi, gizlilik içinde test edin

JSONPath söz dizimini öğrenmenin en hızlı yolu onu çalıştırmaktır. JSONPath Tester bu rehberdeki her ifadeyi canlı değerlendirir: iki motorlu RFC 9535 ve Klasik, Values / Paths / Both sonuç görünümleri, hata ayıklama için normalleştirilmiş yollar ve %100 tarayıcı içi çalıştırma; yükleme yok, kayıt yok ve eval yok, bu yüzden özel payload’lar için güvenli. Burada bir yol kurun, tam olarak istediğiniz düğümleri seçtiğini doğrulayın, ardından doğrulanmış ifadeyi doğrudan kodunuza, testlerinize ya da işlem hattınıza yapıştırın.

JSON iş akışının geri kalanı için, bir örnek yanıtı JSON to TypeScript ile tip tanımlı arabirimlere dönüştürün ya da iki belgeyi alan alan JSON Diff ile karşılaştırın.

Sıkça sorulan sorular

JSONPath ne işe yarar?

JSONPath, JSON’u zorunlu kod olmadan sorgular. Geliştiriciler bunu API yanıtlarından alan çekmek, tümleştirme testlerinde değerleri doğrulamak ve Kubernetes, AWS Step Functions ile Azure Logic Apps yapılandırmalarında alanlara erişmek için kullanır. Elle gezinme yazmanın zahmetli olacağı büyük ya da düzensiz yapılardan veri ayıklamada parlar.

RFC 9535 ile klasik JSONPath arasındaki fark nedir?

Klasik, Stefan Goessner’ın 2007 fiilî lehçesidir; yaygın olarak uygulanmış ama hiç resmî olarak belirtilmemiş, bu yüzden kitaplıklar ayrışmıştır. RFC 9535 ise IETF’nin Şubat 2024 resmî spesifikasyonudur: kesin bir dil bilgisi, sonuçlar için normalleştirilmiş yollar ve beş standart fonksiyon tanımlar. İkisi filtrelerde, birleşimlerde ve eksik üye karşılaştırmasında sınırlarda farklılaşır.

JSONPath filtre ifadeleri nasıl çalışır?

[?()] filtresi yalnızca yüklemi doğru olan öğeleri tutar ve @ geçerli öğedir. Örneğin $.store.book[?(@.price < 10)], 10’un altında fiyatlanan kitapları seçer. Koşulları && ve || ile birleştirebilir, bir üyenin var olup olmadığını sınayabilir ve karakter dizisi ya da sayı değişmezleriyle karşılaştırabilirsiniz.

length()‘i $.store.book.length() olarak kullanabilir miyim?

Hayır. RFC 9535’te length() ve diğer dört fonksiyon yalnızca bir filtre içinde çağrılabilir; $.store.book[?length(@.title) > 15] gibi. Bağımsız bölüm biçimi $.store.book.length(), standart JSONPath değil bir jsonpath-plus uzantısıdır ve RFC 9535 dil bilgisi onu reddeder.

JSONPath, XPath ile aynı mı?

Hayır, ama fikir benzer. XPath, XML’i sorgular; JSONPath, JSON’u sorgular; ikisi de düğümleri yol seçicileriyle konumlandırır. JSONPath, bazı XPath gösterimlerini (*, .. ve []) bilinçli olarak ödünç aldı; benzetmeyi yararlı kılan budur, ama söz dizimi, anlam bilimi ve fonksiyon kümeleri farklıdır ve birbirinin yerine geçmez.

JSONPath’te özyinelemeli iniş (..) ne yapar?

.. işleci, yalnızca doğrudan alt öğeleri değil, belgenin her düzeyini arar. $..author, her yuvalama derinliğinde, nerede görünürse görünsün her author üyesini toplar. Derinlemesine yuvalanmış ya da düzensiz bir yapıdan tek bir alanı çekmenin en hızlı yoludur, ama beklediğinizden çok daha fazla düğümle eşleşebilir; yapabildiğinizde daraltın.

Etiketler: jsonpath json query-language rfc-9535 filter-expression developer-tools