JSONPath test aracı
RFC 9535 JSONPath sorgularını JSON'a karşı test edin: seçiciler, filtreler, beş işlevin tümü ve her eşleşmenin normalleştirilmiş yolu — tümü tarayıcınızda.
- Yol
$['store']['book'][0]['title']"Sayings of the Century" - Yol
$['store']['book'][2]['title']"Moby Dick"
Nihayet bir standardı olan bir sorgu dili
JSONPath, JSON için XPath'in XML için olduğu şeydir: bir belgenin parçalarını göstermeye yarayan küçük bir dil. $.store.book[0].title gibi bir ifade yazarsınız ve eşleşen düğümleri seçer. Fikir, Stefan Goessner'in 2007 tarihli bir blog yazısından gelir ve on yedi yıl boyunca o yazı tek başvuruydu — bu da her kütüphanenin boşlukları farklı doldurması demekti. Tek başına $.. neyi seçer? $[1,2] sırayla dönmeyi garanti eder mi? Bir filtre var olmayan bir değeri nasıl karşılaştırır? Üç JSONPath kütüphanesine sorun, üç yanıt alabilirsiniz.
2024'te yayımlanan RFC 9535 sonunda hepsini sabitledi. Bu test aracı folkloru değil o standardı hedefler. Sorguyu RFC'nin dediği gibi çalıştırır, her eşleşmeyi tam konumuyla gösterir ve — önemlisi — daha eski bir lehçede geçerli ama RFC 9535'te geçersiz bir sorguyu, başka bir aracın farklı yapacağı standart dışı bir şeyi sessizce yapmak yerine sorunun nerede olduğunu söyleyerek reddeder.
Segmentler ve seçiciler
Bir sorgu, kök tanımlayıcısı $ ve ardından gelen bir segment dizisidir ve her segment aldığı düğümlere bir veya daha fazla seçici uygular. Beş seçici vardır:
- Ad — $.store veya $["store"] bir üyenin değerini seçer. Nokta biçimi bir kısaltmadır; köşeli parantez ve tırnak biçimi, boşluk veya noktalama içerenler dahil her anahtar için çalışır.
- Joker — * bir nesnenin her üyesini veya bir dizinin her öğesini seçer.
- Dizin — [0] bir dizi öğesini seçer ve negatif bir dizin sondan sayar, dolayısıyla [-1] sonuncudur.
- Dilim (slice) — [start:end:step] bir aralık seçer, tıpkı Python'daki gibi: [1:3] öğe 1 ve 2'dir, [::-1] tersine çevirir, [::2] birer atlayarak alır.
- Filtre — [?<ifade>] yalnızca ifadenin doğru olduğu öğeleri veya üyeleri tutar (aşağıda açıklanmıştır).
Bir parantez aynı anda birkaç seçici tutabilir: [0, 2, "title"] tek bir segmentte üç şey seçer. Ve bir segment bir alt segment (tek bir nokta veya parantez) ya da bir alt öğe segmenti (..) olabilir; ikincisi düğümde ve tüm alt öğelerinde arar — $..author belgenin herhangi bir yerindeki her author'ı bulur.
Filtreler ve hiçliği karşılaştırmanın dört yolu
Bir filtre seçicisi her öğeyi mantıksal bir ifadeyle sınar; ifadede @ geçerli öğeye, $ ise belgenin tamamına atıfta bulunur. İfade değerleri karşılaştırabilir (==, !=, <, <=, >, >=), testleri && ve || ve ! ile birleştirebilir ve yalnızca varlığı sınayabilir: $..book[[email protected]] ISBN'i olan kitapları tutar, çünkü @.isbn yalnızca anahtar mevcut olduğunda bir düğüm seçer.
İnce nokta, var olmayan bir şeyi karşılaştırmaktır. Bir karşılaştırmanın solundaki veya sağındaki bir sorgu ya bir değer ya da hiçlik verir. RFC bunu kesin tanımlar: hiçlik hiçliğe eşittir, hiçlik hiçbir gerçek değere eşit değildir ve hiçliğe karşı herhangi bir sıra testi (<, >) yalnızca yanlıştır. Böylece @.price < 10, price'ı olmayan bir öğeyi hata vermek yerine sessizce atlar — genellikle istediğiniz ve her zaman standardın söylediği şey budur.
Beş işlev
RFC 9535, bir filtre içinde çağırabileceğiniz beş işlev ekler:
- length() — bir dizenin (karakterle sayılan), bir dizinin veya bir nesnenin uzunluğu.
- count() — bir sorgunun kaç düğüm seçtiği, böylece sayıya göre filtreleyebilirsiniz: [?count(@.chapters) > 3].
- value() — bir sorgunun seçtiği tek değer veya sıfır ya da çok seçerse hiçlik.
- match() — bir dizenin bir düzenli ifadeyle tümüyle eşleşip eşleşmediği.
- search() — bir düzenli ifadenin bir dizenin herhangi bir yerinde bulunup bulunmadığı.
Standart bunların nasıl kullanıldığı konusunda katıdır ve bu test aracı bunu ayrıştırma sırasında uygular: length() tam olarak bir değer alır, dolayısıyla length(@.*) — çok sayıda düğüm seçebilecek bir sorgu — sessizce yanlış davranan bir sorgu değil, bir sözdizimi hatasıdır. Aynı şekilde match() doğru ya da yanlış döndürür, bu yüzden match(@.a, "x") == true yazmak reddedilir, çünkü mantıksal bir sonuç karşılaştırılan bir şey değildir.
Düzenli ifadeler I-Regexp'tir
match() ve search() JavaScript'in düzenli ifadelerini kullanmaz; I-Regexp'i (RFC 9485) kullanır; bu, tüm dillerde aynı davranmak üzere tasarlanmış küçük, taşınabilir bir alt kümedir. Çoğu beklediğiniz gibidir — karakter sınıfları, niceleyiciler, almaşıklık, büyük harf için \p{Lu} gibi Unicode özellikleri. Tek tuzak noktadır: I-Regexp'te . satır başı veya satır beslemesi dışında herhangi bir karakterle eşleşir, bu da JavaScript'in noktasının dışladığı Unicode satır ayırıcıları U+2028 ve U+2029 ile eşleştiği anlamına gelir. Bu test aracı I-Regexp'i sadakatle derler, böylece bir desen burada uyumlu bir sunucunun değerlendireceği gibi davranır.
İki işlev arasındaki fark yalnızca sabitlemedir: match tüm dizenin eşleşmesini ister, search ise deseni onun herhangi bir yerinde arar. match(@, "a.*") "abc"yi kabul eder; search(@, "b") b içeren herhangi bir dizeyi kabul eder.
Normalleştirilmiş yollar ve tarayıcıda çalıştırma
Her eşleşme için bu test aracı bir Normalized Path gösterir — RFC'nin tanımladığı kanonik konum, köşeli parantez ve tırnak biçiminde yazılır: $['store']['book'][0]['author']. Çok sayıda düğüm seçebilen sorgunun aksine, normalleştirilmiş bir yol yalnızca ad ve dizin seçicileri ve sabit bir tırnak stili kullanarak tam olarak birini gösterir. "Bu eşleşme nereden geldi" sorusunun yanıtıdır ve bir joker sonucunu somut konumlar kümesine geri dönüştürmenizi sağlayan şeydir. Çoğu test aracı değerleri gösterir ve yolları çıkarmayı size bırakır; bu ikisini de gösterir.
Motorun tamamı tarayıcınızda çalışır — JSON ayrıştırılır ve sorgu kendi cihazınızda değerlendirilir, ve yapıştırdığınız hiçbir şey yüklenmez, saklanmaz veya kaydedilmez. Resmi JSONPath Compliance Test Suite'e karşı doğrulanmıştır, böylece yanıtları tek bir kütüphanenin yorumuyla değil standartla uyuşur.
Sıkça sorulan sorular
- Bu hangi JSONPath lehçesini kullanır?
- RFC 9535'i, 2024 IETF standardını, ve resmi JSONPath Compliance Test Suite'e karşı doğrulanmıştır. RFC'den ayrıldıkları yerde eski Goessner geleneklerini kasıtlı olarak kabul etmez; böyle bir sorgu, düzeltebilmeniz için sorunun konumuyla reddedilir.
- Başka bir araçta çalışırken sorgum neden reddedildi?
- Çünkü o araç, RFC 9535'ten birkaç yerde farklılaşan standart öncesi Goessner geleneklerini izler — tek başına $.., [(@.length-1)] gibi betik ifadeleri, baştan sıfırlı dizinler ve özel karakterli tırnaksız adlar hepsi standart dışıdır. RFC bunları iyi tanımlanmış eşdeğerlerle değiştirdi ve bu test aracı RFC'ye bağlı kalır.
- Normalleştirilmiş yol nedir?
- Tek bir düğümün kanonik konumu, RFC'nin tanımladığı köşeli parantez ve tırnak biçiminde yazılır, ör. $['store']['book'][0]['author']. Bir sorgu çok sayıda düğümle eşleşebilir; her eşleşmenin tam olarak bir normalleştirilmiş yolu vardır, bu yüzden test aracı onu her değerin yanında gösterir.
- Bir filtre eksik bir değeri nasıl ele alır?
- Hiçlik olarak, RFC'nin sabitlediği kurallarla: hiçlik hiçliğe eşittir, hiçlik hiçbir gerçek değere eşit değildir ve hiçliği içeren herhangi bir sıra karşılaştırması (<, >) yanlıştır. Böylece @.price < 10, price'ı olmayan bir öğeyi hata fırlatmak yerine yalnızca atlar.
- match() ve search() JavaScript'in düzenli ifadelerini mi kullanır?
- Hayır. Taşınabilir bir alt küme olan I-Regexp'i (RFC 9485) kullanırlar. Başlıca pratik fark noktadır; satır başı ve satır beslemesi dışında her şeyle eşleşir — JavaScript'in noktasının dışladığı U+2028 ve U+2029 dahil. Bu test aracı I-Regexp'i sadakatle derler, böylece sonuçlar uyumlu bir uygulamayla eşleşir.
- match ile search arasındaki fark nedir?
- Sabitleme. match() tüm dizenin desene eşleşmesini, sanki mürabıtlarla çevrilmiş gibi ister; search() desen dizenin herhangi bir yerinde bulunursa başarılı olur. Geri kalan her şey aynıdır.
- JSON'um bir sunucuya gönderiliyor mu?
- Hayır. Belge ayrıştırılır ve sorgu tamamen tarayıcınızda değerlendirilir, ve yapıştırdığınız hiçbir şey yüklenmez veya kaydedilmez. Gerçek bir API yanıtına veya bir yapılandırma dosyasına karşı test etmek güvenlidir.