دليل استعلامات JSONPath: كيفية البحث في بيانات JSON
أصبح JSON اللغة العالمية للويب. ترجع واجهات API نتائج JSON، وتستخدم ملفات التكوين JSON، وتخزن قواعد البيانات مستندات JSON. لكن مع نمو هياكل JSON بشكل أكبر وأعمق تداخلاً، يصبح العثور على قيم محددة أكثر صعوبة. هنا يأتي دور JSONPath. JSONPath هي لغة استعلام تتيح لك استخدام تعبيرات مسار موجزة للتنقل واستخراج البيانات من مستندات JSON، تمامًا كما يفعل XPath مع XML. يغطي هذا الدليل كل شيء من الصيغة الأساسية إلى التصفية المتقدمة مع أمثلة عملية يمكنك تطبيقها فورًا.
ما هو JSONPath؟
JSONPath هي لغة استعلام JSON اقترحها Stefan Goessner في عام 2007. توفر صيغة مضغوطة لاختيار العقد من مستندات JSON، مشابهة لكيفية استهداف محددات CSS لعناصر HTML أو تعبيرات XPath لعقد XML. بدلاً من كتابة حلقات ومنطق شرطي للتنقل في هياكل JSON، تكتب ببساطة تعبيرًا يصف المسار إلى البيانات المطلوبة.
تبدأ تعبيرات JSONPath من العقدة الجذرية لمستند JSON وتتنقل عبر الكائنات والمصفوفات إلى القيم المطلوبة. تدعم اللغة أحرف البدل والنزول التكراري وتقطيع المصفوفات وتعبيرات التصفية، وهي كافية لمعظم احتياجات استخراج البيانات.
مثال مستند JSON
في هذا الدليل، سنستخدم مستند JSON التالي كمثال عملي. هذا هو المثال الكلاسيكي من اقتراح JSONPath الأصلي، مع بيانات إضافية:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J.R.R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}مرجع صيغة JSONPath
تستخدم JSONPath مجموعة صغيرة من العوامل التي تتحد لتشكل استعلامات قوية. إليك المرجع الكامل للصيغة:
| العامل | الوصف | مثال |
|---|---|---|
| $ | العقدة الجذرية للمستند | $ |
| . | عامل فرعي (الوصول إلى خصائص الكائن) | $.store |
| [] | فهرس مصفوفة أو عامل فرعي | $.store.book[0] |
| [*] | بدل لجميع عناصر المصفوفة | $.store.book[*] |
| .. | نزول تكراري (البحث في جميع المستويات) | $..author |
| .key | خاصية كائن مسماة | $.store.bicycle |
| ['key'] | صيغة الأقواس للوصول إلى الخصائص | $['store']['book'] |
| [start:end] | تقطيع المصفوفة (فهرس النهاية غير مضمن) | $.store.book[0:2] |
| [?()] | تعبير تصفية | < 10)] |
| () | تعبير سكريبتي (يعتمد على التطبيق) | $.store.book[(@.length-1)] |
تعبيرات JSONPath الأساسية
الوصول إلى العقدة الجذرية والعقد الفرعية المباشرة
تمثل علامة الدولار $ العقدة الجذرية لمستند JSON. من هناك، تستخدم صيغة النقطة للوصول إلى خصائص الكائن وصيغة الأقواس للوصول إلى فهارس المصفوفات.
| التعبير | النتيجة |
|---|---|
| $ | مستند JSON بالكامل |
| $.store | كائن store (يحتوي على مصفوفة book وكائن bicycle) |
| $.store.bicycle | {"color": "red", "price": 19.95} |
| $.store.bicycle.color | "red" |
| $.store.book | مصفوفة book بالكامل |
| $.store.book[0] | كائن الكتاب الأول |
| $.store.book[0].title | "Sayings of the Century" |
| $.store.book[3].author | "J.R.R. Tolkien" |
صيغة الأقواس
صيغة الأقواس هي بديل لصيغة النقطة، مفيدة عندما تحتوي أسماء الخصائص على أحرف خاصة أو مسافات أو تبدأ برقم:
$.store['book'][0]['title']
$['store']['bicycle']['color']صيغة الأقواس وصيغة النقطة قابلة للتبادل لخصائص الكائن. ومع ذلك، يجب استخدام صيغة الأقواس عندما يكون اسم الخاصية ديناميكيًا أو يحتوي على أحرف غير صالحة في صيغة النقطة.
عامل البدل (*)
عامل البدل * يطابق جميع العناصر في مصفوفة أو جميع الخصائص في كائن. إنه مفيد للغاية لاستخراج جميع القيم في مستوى معين دون معرفة المفاتيح أو الفهارس المحددة.
| التعبير | النتيجة |
|---|---|
| $.store.* | جميع القيم في كائن store (مصفوفة book وكائن bicycle) |
| $.store.book[*] | جميع الكتب في المصفوفة (كائنات الكتب الأربعة) |
| $.store.book[*].author | جميع أسماء المؤلفين: ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"] |
| $.store.*.price | سعر bicycle ومصفوفة book (وليس أسعار الكتب الفردية) |
النزول التكراري: عامل النقطتين (..)
عامل النقطتين .. هو أحد أقوى ميزات JSONPath. يبحث عن المفتاح المحدد في كل مستوى من شجرة JSON، وليس فقط العقد الفرعية المباشرة. فكر فيه كبحث عميق عبر المستند بأكمله.
| التعبير | النتيجة |
|---|---|
| $..author | قيم author في جميع مواقع المستند |
| $..price | جميع قيم price: [8.95, 12.99, 8.99, 22.99, 19.95] |
| $..book[2] | الكتاب الثالث، بحث تكراري |
| $..category | جميع قيم category: ["reference", "fiction", "fiction", "fiction"] |
عامل النزول التكراري مفيد بشكل خاص عندما لا تعرف المسار الدقيق للبيانات المطلوبة، أو عندما يظهر نفس المفتاح في مستويات تداخل متعددة. على سبيل المثال، إذا كانت استجابة API تحتوي على حقول id في مستويات تداخل مختلفة، فإن $..id يجمع جميع المعرفات.
تقطيع المصفوفات
تقطيع المصفوفات يتيح لك اختيار مجموعة من العناصر من مصفوفة. الصيغة [start:end] تختار العناصر من فهرس البداية إلى (ولكن لا تشمل) فهرس النهاية. الفهارس الموجبة والسالبة مدعومة.
| التعبير | النتيجة |
|---|---|
| $.store.book[0:2] | أول كتابين (الفهرس 0 و 1) |
| $.store.book[1:3] | الكتابان الثاني والثالث (الفهرس 1 و 2) |
| $.store.book[-1] | الكتاب الأخير (The Lord of the Rings) |
| $.store.book[-2:] | آخر كتابين |
| $.store.book[:2] | أول كتابين (مثل [0:2]) |
| $.store.book[2:] | الكتاب الثالث وما بعده |
لاحظ أن سلوك التقطيع قد يختلف قليلاً بين تطبيقات JSONPath المختلفة. الصيغة أعلاه تتبع الاصطلاح المستخدم من قبل معظم المكتبات الشائعة ومعيار IETF RFC 9535.
تعبيرات التصفية
تعبيرات التصفية هي حيث تصبح JSONPath قوية حقًا. تتيح لك اختيار العناصر بناءً على الشروط بدلاً من الموضع. صيغة التصفية تستخدم [?(condition)]، حيث يتم تقييم الشرط لكل عنصر.
عوامل المقارنة
تدعم JSONPath عوامل المقارنة التالية في تعبيرات التصفية:
| العامل | المعنى | مثال |
|---|---|---|
| == | يساوي | [?(@.category == "fiction")] |
| != | لا يساوي | [?(@.category != "fiction")] |
| < | أقل من | < 10)] |
| <= | أقل من أو يساوي | <= 8.99)] |
| > | أكبر من | [?(@.price > 15)] |
| >= | أكبر من أو يساوي | [?(@.price >= 12.99)] |
| =~ | مطابقة regex (تطبيق جزئي) | [?(@.author =~ /Tolkien/i)] |
أمثلة تصفية عملية
باستخدام مستند المثال الخاص بنا، إليك تعبيرات تصفية عملية ونتائجها:
Find all books cheaper than $10:
< 10)]ترجع الكتب 'Sayings of the Century' (8.95 دولار) و 'Moby Dick' (8.99 دولار).
Find all fiction books:
$.store.book[?(@.category == "fiction")]ترجع ثلاثة كتب: 'Sword of Honour' و 'Moby Dick' و 'The Lord of the Rings'.
Find books with an ISBN:
$.store.book[?(@.isbn)]ترجع الكتب التي لها خاصية isbn: 'Moby Dick' و 'The Lord of the Rings'. هذا لأن المرشح يتحقق من وجود الخاصية.
Find the most expensive book:
$.store.book[?(@.price > 20)]ترجع 'The Lord of the Rings' (22.99 دولار).
العوامل المنطقية في المرشحات
يمكنك دمج الشروط باستخدام العوامل المنطقية:
< 10 && @.category == "fiction")]
$.store.book[?(@.price > 15 || @.category == "reference")]التعبير الأول يجد كتب الخيال التي يقل سعرها عن 10 دولارات (فقط 'Moby Dick'). الثاني يجد الكتب التي يزيد سعرها عن 15 دولارًا أو تنتمي إلى فئة reference (ترجع 'Sayings of the Century' و 'The Lord of the Rings').
JSONPath مقابل XPath
تم نمذجة JSONPath صراحةً على XPath، وتشترك اللغتان في العديد من أوجه التشابه المفاهيمي. إذا كنت معتادًا على معالجة XML، فإن فهم هذه العلاقة مفيد.
| الوظيفة | JSONPath | XPath |
|---|---|---|
| رمز الجذر | $ | / |
| الوصول الفرعي | .key أو ['key'] | /element |
| فهرس المصفوفة | [0] | [1] (يبدأ من 1) |
| البدل | * | * |
| النزول التكراري | .. | // |
| التصفية | [?(condition)] | [condition] |
| السمات | غير متاح (JSON ليس له سمات) | @attr |
| العقدة الحالية | @ (في المرشحات) | . أو current() |
| الأصل | غير مدعوم | .. |
| المحاور | غير مدعومة | 13 محورًا (ancestor، following، إلخ) |
| نموذج البيانات | كائنات ومصفوفات | عناصر وسمات وعقد نصية |
الفرق الرئيسي هو أن XPath يعمل على نموذج شجري غني بالعناصر والسمات وعقد النص ومساحات الأسماء وتعليمات المعالجة. تعمل JSONPath على نموذج أبسط من الكائنات (خرائط المفتاح والقيمة) والمصفوفات (قوائم مرتبة). هذه البساطة تجعل JSONPath أسهل في التعلم ولكنها أقل تعبيرًا من XPath للاستعلامات المعقدة.
تطبيقات JSONPath العملية
اختبار API
JSONPath لا غنى عنها لاختبار API. عندما ترسل طلبًا إلى API وتتلقى استجابة JSON كبيرة، تتيح لك JSONPath تأكيد قيم محددة دون التنقل يدويًا في الهيكل بأكمله. معظم أدوات اختبار API تدعم JSONPath بشكل أصلي.
على سبيل المثال، في اختبار قد تتحقق من أن سعر الكتاب الأول أقل من 10 دولارات:
// Using a JSONPath assertion in testing
response.jsonPath().get("store.book[0].price").should(equals(8.95));
// Find all books by a specific author
response.jsonPath().get("store.book[?(@.author == 'Herman Melville')].title");
// Returns: ["Moby Dick"]تحويل البيانات
عند دمج أنظمة تستخدم تنسيقات بيانات مختلفة، تساعد JSONPath في استخراج وتحويل حقول محددة. يمكنك استخراج القيم من هيكل JSON وتعيينها إلى آخر دون كتابة كود تنقل معقد.
إدارة التكوين
غالبًا ما تحتوي ملفات التكوين المعقدة على JSON متداخل بعمق. تتيح لك JSONPath الاستعلام عن قيم تكوين محددة دون تحميل وتحليل الهيكل بأكمله. أدوات مثل jq تستخدم صيغة مشابهة لـ JSONPath لمعالجة JSON في خطوط أنابيب سطر الأوامر.
المراقبة والتنبيهات
في أنظمة المراقبة، يمكن لاستعلامات JSONPath استخراج المقاييس من سجلات JSON واستجابات API. يمكنك إعداد تنبيهات تشغل عندما ترجع استعلامات JSONPath قيمًا تتجاوز الحدود.
تطبيقات JSONPath
JSONPath متاحة في كل لغة برمجة تقريبًا. إليك المكتبات الأكثر شيوعًا:
| اللغة | المكتبة | التثبيت |
|---|---|---|
| JavaScript | jsonpath-plus | npm install jsonpath-plus |
| Python | jsonpath-ng | pip install jsonpath-ng |
| Java | JsonPath (Jayway) | Maven: com.jayway.jsonpath |
| C# | Json.NET (Newtonsoft) | NuGet: Newtonsoft.Json |
| Go | gjson | go get github.com/tidwall/gjson |
| PHP | jsonpath | composer require softcreatr/jsonpath |
| Ruby | jsonpath | gem install jsonpath |
مثال JavaScript
< 10)]',
json: data
});
// Returns books with price < 10
Python Example
from jsonpath_ng import parse
data = { /* our sample JSON */ }
# Find all authors
author_expr = parse('$..author')
authors = [match.value for match in author_expr.find(data)]
# ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
# Find cheap books
cheap_expr = parse('$.store.book[?(@.price < 10)]')
cheap_books = [match.value for match in cheap_expr.find(data)]
Common Pitfalls and Tips
- Zero-based vs one-based indexing: JSONPath uses zero-based indexing (the first element is [0]), while XPath uses one-based indexing (the first element is [1]). This is a common source of off-by-one errors.
- Implementation differences: Before the IETF standard (RFC 9535), JSONPath implementations varied in their handling of edge cases like empty results, null values, and filter syntax. Always test your expressions with the specific library you are using.
- Filter performance: Recursive descent with filters (
$..book[?(@.price < 10)]) can be slow on large documents because it must traverse the entire tree. For performance-critical applications, use more specific paths when possible. - Case sensitivity: JSONPath is case-sensitive.
$.Storewill not match$.store. This is consistent with JSON's case-sensitive nature. - الفهرسة من الصفر مقابل الفهرسة من الواحد: تستخدم JSONPath فهرسة من الصفر (العنصر الأول هو [0])، بينما يستخدم XPath فهرسة من الواحد (العنصر الأول هو [1]). هذا مصدر شائع لأخطاء الفرق بواحد.
- اختلافات التطبيقات: قبل معيار IETF (RFC 9535)، اختلفت تطبيقات JSONPath في التعامل مع الحالات الحدية مثل النتائج الفارغة وقيم null وصيغة التصفية. اختبر التعبيرات دائمًا مع مكتبتك المحددة.
المزالق والنصائح الشائعة
في عام 2024، نشرت IETF معيار RFC 9535، الذي وحد JSONPath رسميًا. يعالج المواصفات العديد من الغموض والتناقضات التي كانت موجودة بين التطبيقات. تشمل الجوانب الرئيسية للمعيار:
- < 10)]) يمكن أن يكون بطيئًا على المستندات الكبيرة لأنه يجب أن يتنقل في الشجرة بأكملها. للتطبيقات الحرجة للأداء، استخدم مسارات أكثر تحديدًا كلما أمكن.
- حساسية حالة الأحرف: JSONPath حساسة لحالة الأحرف. $.Store لن يطابق $.store. هذا متسق مع طبيعة JSON الحساسة لحالة الأحرف.
- هروب الأحرف الخاصة: إذا كانت أسماء المفاتيح تحتوي على نقاط أو أقواس، يجب استخدام صيغة الأقواس المقتبسة: $['key.with.dots'] بدلاً من $.key.with.dots.
- لا يوجد تنقل للأصل: على عكس XPath، لا يمكن لـ JSONPath التنقل إلى العقدة الأصلية. لا يوجد مكافئ لـ .. (محور الأصل) في XPath. .. في JSONPath تعني النزول التكراري، وليس الأصل.
إذا كنت تبدأ مشروعًا جديدًا، فضل المكتبات التي تطبق RFC 9535 للحصول على أقصى توافق وسلوك متوقع.
تحتاج إلى استعلام سريع عن بيانات JSON؟ جرب مختبر JSONPath المجاني عبر الإنترنت لتقييم التعبيرات مقابل مستندات JSON في الوقت الفعلي.
جرب باحث JSONPathمعيار IETF: RFC 9535
مثال Python
JSONPath هي لغة استعلام JSON، مشابهة لـ XPath لـ XML. تستخدم تعبيرات المسار للتنقل واستخراج قيم محددة من مستندات JSON. تعبير JSONPath مثل $.store.book[0].title يتيح لك تحديد البيانات بدقة في هياكل JSON المعقدة المتداخلة دون كتابة كود تحليل مخصص.
ما هو JSONPath؟
JSONPath مصممة لهياكل الكائنات والمصفوفات في JSON، بينما XPath مصممة لأشجار العناصر والسمات في XML. تستخدم JSONPath $ كعقدة جذرية، وصيغة النقطة للوصول إلى الكائنات، وصيغة الأقواس للوصول إلى المصفوفات. يستخدم XPath / لفصل المسار، و @ للوصول إلى السمات. JSONPath أبسط ولكنها أقل غنى بالميزات من XPath.
كيف يختلف JSONPath عن XPath؟
النقطتان (..) في JSONPath هما عامل النزول التكراري. يبحث عن المفتاح المسمى في جميع مستويات هيكل JSON، وليس فقط العقد الفرعية المباشرة. على سبيل المثال، $..author يجد جميع مفاتيح author في أي مكان في المستند بأكمله، بغض النظر عن مدى عمق تداخلها.
ماذا تعني النقطتان (..) في JSONPath؟
< و ><= و >< 10)] يجد جميع الكتب التي يقل سعرها عن 10 دولارات.
هل يمكن لـ JSONPath تصفية البيانات حسب الشروط؟
اقترح Stefan Goessner JSONPath في الأصل عام 2007 بدون مواصفات رسمية، مما أدى إلى اختلافات بين التطبيقات. في عام 2024، نشرت IETF معيار RFC 9535 لوحد JSONPath رسميًا. تتقارب التطبيقات الحديثة نحو هذا المعيار، لكن بعض المكتبات القديمة قد لا تزال لديها اختلافات طفيفة في الصيغة.