JSON Toolkit

व्यवहार में JSONPath क्वेरी भाषा

मुख्य बात: 2024 में JSONPath को आखिरकार औपचारिक मानक RFC 9535 मिला। यह लेख सिंटैक्स, filter semantics, functions और implementations के ऐतिहासिक अंतर समझाता है।

मध्यम~12 मिनट पढ़ें2026-10-30 को प्रकाशित2026-10-30 को अपडेट किया गया
व्यवहार में JSONPath क्वेरी भाषा का कवर

सारांश: पहले स्पष्ट पथ से locate करें और उसके ऊपर filter लगाएँ, और व्यंजक RFC 9535 के अनुरूप लिखें; किसी एक निश्चित फ़ील्ड के लिए property access या JSON Pointer, और aggregation के लिए jq या कोड इस्तेमाल करें।

आपने शायद $.store.book[?(@.price < 10)].title जैसे व्यंजक देखे होंगे, लेकिन यह 2024 में ही अंतरराष्ट्रीय मानक बना।

1. De facto मानक से औपचारिक मानक तक

JSONPath को Stefan Gössner ने 2007 में प्रस्तावित किया था, और लंबे समय तक एकमात्र "विनिर्देश" एक ब्लॉग पोस्ट था, जिसमें हर भाषा की implementation अपनी-अपनी करती थी:

  • filters को कोष्ठक चाहिए या नहीं (?(@.a) बनाम ?@.a);
  • array index [-1] समर्थित है या नहीं;
  • परिणाम "मान" लौटाता है या "मान और paths";
  • script expressions (?(@.price < $.max)) अनुमत हैं या नहीं।

फरवरी 2024 में प्रकाशित RFC 9535 ने इन विचलनों को एक ही सिंटैक्स और semantics में समेट दिया और आधिकारिक compliance test suite दिया। नए प्रोजेक्ट्स को RFC 9535 का पालन करना चाहिए; पुराने प्रोजेक्ट्स migrate करते समय पहले implementation version पक्का करें।

2. सिंटैक्स चीट शीट

सिंटैक्स अर्थ उदाहरण
$ Root node $.store
@ Filter के अंदर वर्तमान node $[?@.price < 10]
.name Child node (नाम [A-Za-z_][A-Za-z0-9_]* से मेल खाना चाहिए) $.store.book
['name'] Child node (कोई भी नाम, non-ASCII और बिंदुओं सहित) $['store']['书']
[0] Array index; ऋणात्मक संख्याएँ अंत से गिनती हैं $.book[0], $.book[-1]
[0,2] कई indices / कई नाम $.book[0,2]
[1:3] Slice, start शामिल और end शामिल नहीं $.book[1:3]
[::2] Step के साथ slice $.book[::2]
[*] सभी child nodes के लिए wildcard $.book[*].title
..name Recursive descent, किसी भी गहराई पर खोज $..price
..[*] पुनरावर्ती रूप से सभी nodes लें $..*
[?<expr>] Filter selector $.book[?@.price < 10]

एक semantic याद रखना ज़रूरी है: JSONPath node set (nodelist) लौटाता है, एकल मान नहीं। जब केवल एक node match हो, तब भी परिणाम लंबाई एक की list होती है।

3. एक नमूने से पूरे सिंटैक्स को चलाना

{
  "store": {
    "book": [
      { "title": "JSON 权威指南", "price": 8.95, "tags": ["json", "spec"] },
      { "title": "数据交换格式史", "price": 12.99, "tags": ["history"] },
      { "title": "解析器实现原理", "price": 8.99, "tags": ["parser", "json"] }
    ],
    "bicycle": { "color": "red", "price": 19.95 }
  },
  "expensive": 10
}
व्यंजक परिणाम
$.store.bicycle.color ["red"]
$..price 4 कीमतें (bicycle की कीमत सहित)
$.store.book[*].title 3 titles
$.store.book[?@.price < 10].title Book 1 और 3 के titles
$.store.book[?@.tags] वे सभी books जिनमें tags है (existence test)
$.store.book[-1].title अंतिम book का title
$..book[0,1] पहली दो books
$.store.book[?@.price < $.expensive] वाक्यात्मक रूप से implementation पर निर्भर; RFC 9535 cross-root संदर्भ अनुमति नहीं देता

अंतिम पंक्ति एक ऐतिहासिक जाल है: कई implementations filter के अंदर cross-node तुलना के लिए $.expensive अनुमति देती हैं, जिसे RFC 9535 स्पष्ट रूप से वर्जित करता है — filter केवल वर्तमान node @ तक पहुँच सकता है। जब आपको वैश्विक threshold से तुलना करनी हो, threshold को query function के argument के रूप में पास करें।

4. Filters क्या व्यक्त कर सकते हैं

RFC 9535 filter व्यंजक चार तरह की रचनाएँ समर्थित करते हैं:

Logic:       &&  ||  !          उदा. ?@.price < 10 && @.tags
Comparison:  ==  !=  <  <=  >  >=
Existence:   नंगा पथ             उदा. ?@.tags (अस्तित्व जाँचता है)
Functions:   length() count() match() search() value()

कुछ व्यावहारिक उदाहरण:

// 8 और 10 के बीच कीमत
$.store.book[?@.price >= 8 && @.price <= 10]

// Title में "JSON" है (regex match; दूसरा argument एक I-Regexp है)
$.store.book[?match(@.title, ".*JSON.*")]

// एक से अधिक tag
$.store.book[?length(@.tags) > 1]

// list के बजाय पहला matched मान लें (value() single-node set को मान बनाता है)
$.store.book[?@.price < 9].title.value()

match() पूरी स्ट्रिंग का match है और search() उपस्ट्रिंग की खोज है; अंतर्निहित regex dialect I-Regexp है (RFC 9485 का उपसमुच्चय), जो न backreferences समर्थित करता है न lookaround — यह सीमा भी है और regex DoS के विरुद्ध एक उपयोगी ढाल भी।

5. Implementation अंतर: migrate करने से पहले जाँचें

Implementation भाषा RFC 9535 समर्थन टिप्पणियाँ
jsonpath-plus JavaScript अधिकतर संगत Extension functions और script expressions समर्थित; अधिक सक्षम पर सख्ती से मानक नहीं
jsonpath (dchester) JavaScript आंशिक ?() सिंटैक्स वाली पुरानी library, result संरचना अलग
ojg / gjson Go ojg का अच्छा समर्थन gjson दूसरा पथ सिंटैक्स इस्तेमाल करता है, JSONPath नहीं
jsonpath-ng Python आंशिक Extensions समर्थित और काफ़ी ढीला
Jayway JsonPath Java आंशिक व्यापक ecosystem; ऐतिहासिक व्यवहार RFC से अलग

Migrate करने से पहले तीन जाँच:

  1. Filter कोष्ठक आवश्यक हैं या नहीं;
  2. -1 जैसे ऋणात्मक indices समर्थित हैं या नहीं;
  3. परिणाम "मानों का array" है या "{path, value} objects का array"।

तीसरी सबसे आसानी से फिसलती है: frontend result[0] पढ़ता है, और library बदलने के बाद उसे object मिलता है, जिससे पेज खाली हो जाता है।

6. Performance और Security

Performance

  • JSONPath मूलतः एकल traversal है जिसकी जटिलता O(number of nodes) है, और यह indexes इस्तेमाल नहीं कर सकता;
  • .. वाला recursive descent सबसे महँगा है; अगर पहले $.store.book से locate करके फिर filter कर सकते हैं, तो $..book न लिखें;
  • व्यंजकों को एक बार compile करें और दोबारा उपयोग करें (अधिकांश libraries compile या caching देती हैं), हर क्वेरी पर फिर से parse न करें;
  • 100,000 से अधिक nodes वाले दस्तावेज़ों के लिए पहले JSON Pointer से सटीक extraction या server पर jq से preprocessing पर विचार करें।

Security

  • उपयोगकर्ता इनपुट से आने वाले व्यंजकों की लंबाई और nesting गहराई सीमित होनी चाहिए;
  • JSONPath को authorization न सौंपें — यह केवल पढ़ सकता है, और "कौन-से फ़ील्ड अदृश्य हैं" व्यक्त नहीं कर सकता;
  • जब match() का regex उपयोगकर्ताओं से आता है, उसकी जटिलता सीमित करें; भले यह PCRE से सुरक्षित है, लंबाई की सीमा फिर भी सलाहनीय है।

7. JSONPath का उपयोग कब न करें

  • आपको केवल एक निश्चित फ़ील्ड चाहिए → सीधे data.store.bicycle.color इस्तेमाल करें;
  • बदलने के बाद वापस लिखना है → JSON Pointer या patch इस्तेमाल करें; JSONPath वापस नहीं लिखता;
  • आपको aggregation (summing, grouping) चाहिए → jq, SQL या कोड इस्तेमाल करें; JSONPath केवल select करता है;
  • दस्तावेज़ बहुत बड़ा है और आपको केवल कुछ फ़ील्ड चाहिए → पूरा पेड़ पहले memory में पढ़ने के बजाय streaming parser इस्तेमाल करें।

8. Checklist

  • [ ] व्यंजक RFC 9535 का पालन करते हैं और cross-root संदर्भों पर निर्भर नहीं हैं;
  • [ ] यह स्पष्ट है कि परिणाम node set है; एकल मान के लिए [0] या value() इस्तेमाल करें;
  • [ ] व्यंजक precompiled और दोबारा उपयोग किए जाते हैं;
  • [ ] उपयोगकर्ता-नियंत्रित व्यंजकों पर लंबाई और जटिलता सीमाएँ हैं;
  • [ ] Implementation बदलते समय आधिकारिक compliance test cases चलाए जाते हैं।

FAQ

JSON Pointer और JSONPath के बीच कैसे चुनूँ?

जब आपको केवल एक निश्चित फ़ील्ड चाहिए तो साधारण property access या JSON Pointer इस्तेमाल करें; जब filters, wildcards या recursive descent चाहिए तो JSONPath पर हाथ बढ़ाएँ। JSONPath केवल select करता है और कभी वापस नहीं लिखता, इसलिए write-back JSON Pointer या patch का काम है।

Filter $.expensive को संदर्भित क्यों नहीं कर सकता?

RFC 9535 cross-root संदर्भों को स्पष्ट रूप से वर्जित करता है; filter केवल वर्तमान node @ तक पहुँच सकता है। इसके बजाय threshold को query function के argument के रूप में पास करें। पुरानी implementations सिंटैक्स स्वीकार करती हैं, पर library बदलने या upgrade करने पर यह टूट जाता है।

क्या मान पढ़ने के लिए result[0] पर निर्भर रहना चाहिए?

केवल तब जब आप पुष्टि कर लें कि वर्तमान implementation मानों का array लौटाती है। कुछ libraries {path, value} objects लौटाती हैं, तो result[0] object बन जाता है और पेज खाली हो जाता है। एकल मान [0] या value() से पढ़ें, और implementation बदलने से पहले आधिकारिक compliance suite चलाएँ।

संदर्भ

मेल खाते उपकरण

संबंधित लेख

JSON Pointer, Patch और Merge Patch

तीन छोटे विनिर्देश मिलकर एक change protocol बनाते हैं: Pointer locate करता है, Patch ठीक-ठीक edit करता है, Merge Patch आंशिक रूप से merge करता है। गलत चुनाव arrays और concurrency पर चोट पहुँचाता है।

मध्यम~12 मिनट पढ़ें2026-10-30 को अपडेट किया गया

JSON parsing और processing लाइब्रेरी तुलना

Native APIs सबसे तेज़ हैं, tolerant parsers offsets देते हैं। तीन बातों से चुनें: error location, मूल text सुरक्षित रहता है या नहीं, और सीमाएँ स्पष्ट हैं या नहीं।

मध्यम~11 मिनट पढ़ें2026-10-30 को अपडेट किया गया

JSONPath Filters विस्तार से: Recursion, Slices और Multi-Condition Matching

Recursive descent, slices और multi-condition filters वहीं हैं जहाँ JSONPath शक्तिशाली और दुरुपयोग किया गया बनता है। इसमें filter semantics, result आकार और library अंतर शामिल हैं।

मध्यम~10 मिनट पढ़ें2026-10-31 को अपडेट किया गया