JMESPath शुरुआती लोगों के लिए: JSONPath से बेहतर projection क्वेरी
मुख्य बात: JMESPath ऑब्जेक्ट्स के बैच को JSONPath की तुलना में अधिक सीधे ढालता है। यह शुरुआती मार्गदर्शिका सिंटैक्स, projections, pipes, अंतर्निहित functions और AWS CLI के उपयोग को कवर करती है।

सारांश: स्थिति के आधार पर ढूँढ़ने के लिए JSON Pointer, filter या recursion के लिए JSONPath, और जब परिणाम को नया आकार देना हो या कमांड लाइन पर project करना हो तो JMESPath इस्तेमाल करें; किसी एक ज्ञात फ़ील्ड के लिए इनमें से कुछ भी नहीं।
अगर आपका लक्ष्य ऑब्जेक्ट्स के एक बैच को भिन्न आकार में ढालना है, तो JMESPath अक्सर JSONPath से अधिक सीधा होता है। यह nodes नहीं ढूँढ़ता; यह परिणाम बनाता है।
1. JMESPath क्या है
JMESPath JSON के लिए विशेष रूप से बनाई गई एक क्वेरी भाषा है। इसे मूल रूप से AWS CLI के आउटपुट को फ़िल्टर करने के लिए बनाया गया था और बाद में jmespath.js, jmespath.py और go-jmespath जैसे implementations के ज़रिए कई भाषाओं में फैल गया। इसका लक्ष्य JSONPath से अलग है:
- JSONPath पथ और शर्त के आधार पर nodes का एक समूह चुनने पर केंद्रित है, और node set लौटाता है;
- JMESPath इनपुट JSON को रूपांतरित करने पर केंद्रित है, और किसी भी आकार का मान लौटाता है।
यही अंतर JMESPath को list projections, फ़ील्ड renaming और परिणाम trimming में विशेष रूप से अच्छा बनाता है, जैसे किसी API response के बीस फ़ील्ड घटाकर वही तीन फ़ील्ड रखना जो frontend को वास्तव में चाहिए। अगर आपने JSONPath की मूल बातें अभी नहीं पढ़ीं, तो व्यवहार में JSONPath क्वेरी भाषा से शुरू करें।
2. मूल सिंटैक्स: identifiers से indices तक
JMESPath JSONPath से कम चिह्न इस्तेमाल करता है और अधिक extraction व्यंजक जैसा पढ़ा जाता है:
| सिंटैक्स | अर्थ | उदाहरण |
|---|---|---|
name |
ऑब्जेक्ट के सदस्य तक पहुँच | people |
a.b |
nested सदस्यों तक पहुँच | store.bicycle.color |
[0] |
array index तक पहुँच | people[0] |
[-1] |
अंतिम element तक पहुँच | people[-1] |
[0:2] |
slice, start शामिल और end शामिल नहीं | people[0:2] |
[*] |
list projection | people[*].name |
[] |
flatten projection | people[].tags[] |
[?condition] |
filter projection | people[?age > 18] |
{key: expr} |
multi-select hash | {name: name, age: age} |
[expr, expr] |
multi-select list | [name, age] |
| |
बाएँ परिणाम को दाईं ओर pipe करें | people[*].age | [0] |
एक न्यूनतम उदाहरण:
{
"people": [
{ "name": "Alice", "age": 31, "city": "Shanghai" },
{ "name": "Bob", "age": 17, "city": "Beijing" }
]
}
people[0].name → "Alice"
people[-1].city → "Beijing"
people[0:2].name → ["Alice", "Bob"]
ध्यान दें कि people[0:2].name array क्यों लौटाता है: slice एक list लौटाता है, और उसके बाद का .name उस list के हर element पर स्वतः project हो जाता है। यही JMESPath और साधारण object access के बीच सबसे बड़ा अंतर है।
3. Projections: एक list को दूसरी list में बदलना
Projection JMESPath की मूल अवधारणा है। यह दो चरणों में काम करता है: list के हर element का मूल्यांकन करें, फिर परिणामों को एक नई list में एकत्र करें। जो elements null पर मूल्यांकित होते हैं, वे स्वतः हट जाते हैं।
people[*].name // ["Alice", "Bob"]
people[*].{name: name, age: age} // ऑब्जेक्ट्स की सूची
people[?age > 18].name // ["Alice"]
दूसरी पंक्ति एक विशिष्ट projection व्यंजक है: people[*].{name: name, age: age}। यह हर element को { "name": ..., "age": ... } के रूप में फिर से बनाता है और अतिरिक्त city फ़ील्ड छोड़ देता है। JSONPath की तुलना में, जो आपको nodes देता है जिन्हें आप फिर कोड में map करते हैं, यह एक loop बचाता है।
दो तरह के projections को अलग पहचानना ज़रूरी है:
[*]मूल list संरचना बनाए रखता है और null मान छोड़ देता है;[]एक flatten projection है जो पहले nested lists का एक स्तर समेटता है, जोpeople[].tags[]जैसे व्यंजकों के लिए उपयुक्त है जिन्हें "सभी लोगों के सभी tags" चाहिए।
4. Pipes और Multi-Select
Pipe | का अर्थ है "वर्तमान projection रोको और परिणाम को नया इनपुट मानो"। इसका सबसे आम उपयोग projection के बाद index लेना है:
people[*].name | [0] → "Alice"
people[*].age | sort(@) | [-1] → अधिकतम आयु
Pipe के बिना people[*].name[0] का अर्थ हर name का पहला अक्षर लेना हो जाता है, जो आप नहीं चाहते। Pipe JMESPath में सबसे आसानी से छूटने वाला और सबसे उपयोगी चिह्न है।
Multi-select के दो रूप हैं:
// Multi-select hash: परिणाम एक ऑब्जेक्ट है
people[0].{name: name, age: age}
// Multi-select list: परिणाम एक array है
people[0].[name, age]
Multi-select hashes नामित परिणाम बनाने के लिए अच्छे हैं, जबकि multi-select lists स्थिति के आधार पर उपभोग के लिए अच्छी हैं। दोनों को projections के अंदर nest किया जा सकता है, लेकिन ध्यान दें: multi-select hash में जिस key का मान null है वह भी रखा जाता है, जबकि projection पूरे null element को हटा देता है।
5. अंतर्निहित Functions
JMESPath मानक functions का एक समूह परिभाषित करता है। आम वाले हैं:
| Function | उद्देश्य | उदाहरण |
|---|---|---|
length() |
लंबाई प्राप्त करें | length(people) |
sort() |
मानों को क्रमबद्ध करें | sort(people[*].age) |
sort_by() |
किसी फ़ील्ड के आधार पर क्रमबद्ध करें | sort_by(people, &age) |
max() / min() |
अधिकतम / न्यूनतम | max(people[*].age) |
sum() |
मानों का योग | sum(people[*].age) |
keys() |
ऑब्जेक्ट की keys प्राप्त करें | keys(people[0]) |
contains() |
समावेश जाँचें | contains(name, "Ali") |
to_string() |
स्ट्रिंग में बदलें | to_string(age) |
sort_by का दूसरा argument एक & व्यंजक है, जिसका अर्थ है "हर element से यह फ़ील्ड लें":
sort_by(people, &age)[*].name
ये functions JMESPath को सरल aggregation करने देते हैं, जबकि JSONPath केवल selection के लिए बना है; summing और grouping के लिए सामान्यतः jq या कोड चाहिए।
6. JSONPath के साथ आमने-सामने तुलना
| पक्ष | JSONPath | JMESPath |
|---|---|---|
| मुख्य लक्ष्य | nodes चुनना | डेटा रूपांतरित करना |
| Root चिह्न | $ |
कोई नहीं; फ़ील्ड नाम सीधे लिखें |
| वर्तमान node | @ |
@ (केवल function arguments में) |
| Filter | [?(@.age > 18)] |
[?age > 18] |
| Wildcard | [*] |
[*] या [] |
| नए ऑब्जेक्ट बनाना | समर्थित नहीं | {name: name} |
| Pipes | समर्थित नहीं | | |
| मानक | RFC 9535 | JMESPath Specification |
एक वाक्य में निर्णय मार्गदर्शिका:
- जब आपको केवल शर्त से मेल खाते nodes ढूँढ़ने हों तो JSONPath इस्तेमाल करें;
- जब आपको परिणाम को उस रूप में ढालना हो जिसकी frontend अपेक्षा करता है तो JMESPath इस्तेमाल करें;
- जब आप कोई एक ज्ञात फ़ील्ड पढ़ रहे हों तो दोनों में से कोई नहीं; सीधे property access करें।
अगर क्वेरी परिणाम को दस्तावेज़ में वापस लिखना है, तो दोनों भाषाएँ उपयुक्त नहीं हैं। इसके बजाय JSON Pointer और patches इस्तेमाल करें; देखें JSON Pointer, Patch और Merge Patch।
7. AWS CLI में JMESPath
AWS CLI का --query parameter JMESPath है, जो इसका सबसे व्यापक उपयोग है:
aws ec2 describe-instances \
--query 'Reservations[].Instances[].{Id: InstanceId, State: State.Name, Type: InstanceType}' \
--output table
यह कमांड तीन काम करता है: [] से दो nested lists को flatten करता है, multi-select hash से केवल तीन फ़ील्ड रखता है, और --output table से परिणाम को तालिका के रूप में दिखाता है। JSONPath से आपको अधिक स्तर चाहिए होंगे और "rename के साथ trim" वाला प्रभाव नहीं मिलेगा।
अन्य सामान्य रूप:
# केवल चल रहे instances
aws ec2 describe-instances --query 'Reservations[].Instances[?State.Name==`running`].[InstanceId,PublicIpAddress]'
# Name tag का मान
aws ec2 describe-instances --query 'Reservations[].Instances[].Tags[?Key==`Name`].Value[]'
ध्यान दें कि backticks literals को घेरते हैं, strings को नहीं। AWS CLI में strings के लिए single quotes और JSON literals के लिए backticks इस्तेमाल होते हैं। यही अंतर शुरुआती लोगों की सबसे आम गलतियों में से एक है।
8. आम गलतियाँ
[*]और[]में भ्रम: पहला nesting बनाए रखता है, दूसरा एक स्तर flatten करता है, और परिणामी संरचनाएँ पूरी तरह अलग होती हैं;- Pipe भूल जाना:
people[*].name[0]हर name का पहला अक्षर लेता है, पहला name नहीं; - Filter के अंदर
@लिखना: JMESPath filters सीधे फ़ील्ड नाम इस्तेमाल करते हैं, इसलिए[?@.age > 18]गलत है; nullको खाली स्ट्रिंग मानना: projectionsnullहटा देते हैं, लेकिन multi-select hashes key रख लेते हैं;- AWS CLI में literals के चारों ओर double quotes लगाना: shell पहले उन्हें expand कर देता है और व्यंजक बदल देता है।
Debugging सलाह: किसी व्यंजक को वास्तविक डेटा पर लागू करने से पहले यथासंभव छोटे इनपुट पर जाँचें, और AWS CLI में raw परिणाम देखने के लिए --output json जोड़ें। रोज़मर्रा के JSON editing और formatting के लिए JSON Editors और कमांड-लाइन उपकरण के साथ इस्तेमाल करने से फ़ील्ड पथ ढूँढ़ना बहुत तेज़ हो जाता है।
FAQ
क्या JMESPath और JSONPath एक साथ इस्तेमाल हो सकते हैं?
हाँ, लेकिन सामान्यतः इसकी ज़रूरत नहीं होती। एक आम तरीका है JMESPath से छोटे ऑब्जेक्ट को trim करना, फिर कोड में साधारण property access करना। अगर आपको वास्तव में पहले पथ से locate करना और फिर बदलना है, तो पढ़ने के लिए JSONPath और लिखने के लिए JSON Pointer, यही अधिक स्पष्ट श्रम-विभाजन है।
people[*].name एक स्ट्रिंग के बजाय कुछ और क्यों लौटाता है?
क्योंकि [*] एक projection है, और परिणाम हमेशा एक list होता है, तब भी जब केवल एक ही व्यक्ति हो। एकल मान पाने के लिए pipe और index जोड़ें: people[*].name | [0]।
Projection के अंदर null का क्या होता है?
List projection null पर मूल्यांकित होने वाले elements को स्वतः छोड़ देता है, इसलिए परिणाम मूल list से छोटा हो सकता है। Multi-select hash key रखता है और null मान बनाए रखता है, जो API responses बनाते समय महत्वपूर्ण है।
क्या JMESPath aggregation और grouping कर सकता है?
यह sum(), max() और sort_by() से बुनियादी aggregation कर सकता है। Grouping, joins और window functions मानक से बाहर हैं। जटिल विश्लेषण jq, SQL या कोड पर छोड़ें।
JMESPath और JSONPath के बीच निर्णय कैसे लूँ?
जब आपको पथ और शर्त के आधार पर nodes चुनकर node set प्राप्त करना हो तो JSONPath इस्तेमाल करें; जब आपको परिणाम को उस रूप में ढालना हो जिसकी frontend अपेक्षा करता है, फ़ील्ड renaming और trimming के साथ, तो JMESPath इस्तेमाल करें। जब आप कोई एक ज्ञात फ़ील्ड पढ़ रहे हों तो दोनों में से कोई नहीं; सीधे property access करें।
क्या पहला projected मान लेने के लिए pipe इस्तेमाल करना चाहिए?
हाँ। people[*].name एक projection है, इसलिए परिणाम हमेशा एक list होता है; pipe के बिना people[*].name[0] हर name का पहला अक्षर लेता है। पहला मान पाने के लिए people[*].name | [0] लिखें।