مقارنة مكتبات تحليل JSON ومعالجته
الخلاصة: واجهات API الأصلية هي الأسرع، والمحللات المتسامحة تمنحك الإزاحات. اختر وفق ثلاثة أمور: موقع الخطأ، والحفاظ على النص الأصلي، وصراحة الحدود.

الخلاصة: صنّف الحاجة أولًا، ثم قارن التنفيذات — استخدم JSON.parse الأصلي للقراءة فقط، وjsonc-parser عندما تحتاج إلى إزاحات أو يجب الحفاظ على التنسيق الأصلي، ولا تضف مكتبات الاستعلام أو التصحيح إلا حيث تلزم؛ حمّل المكتبات الكبيرة كسولًا لكل صفحة وتخلّص من غير المصانة منها.
تزعم كل مكتبة أنها "سريعة وصغيرة وكاملة". ما يميزها فعلًا هو مقدار المعلومات التي تمنحك إياها عند حدوث خطأ.
1. أربع فئات بحسب الغرض
| الفئة | المكتبات الممثلة | ما تحله |
|---|---|---|
| التحليل القياسي | JSON.parse / JSON.stringify |
الصياغة ↔ الكائن، السرعة أولًا |
| التحليل المتسامح + التحرير | jsonc-parser، json5 |
مدخلات بتعليقات، أخطاء دقيقة إلى الإزاحة، تعديلات تحفظ التنسيق |
| الاستعلام | jsonpath-plus، jsonpath |
اختيار العقد بتعبير |
| التغيير | fast-json-patch، immer |
توليد/تطبيق التصحيحات، تحديثات غير قابلة للتغيير |
حدّد الفئة التي تنتمي إليها أولًا، ثم قارن التنفيذات المحددة — وإلا فمن السهل استخدام مكتبة استعلام لأداء مهمة محلل.
2. مقارنة جانبية
| المكتبة | موقع الخطأ | التسامح (التعليقات/الفواصل الزائدة) | تحافظ على التنسيق الأصلي | السياقات المناسبة |
|---|---|---|---|---|
JSON.parse |
الرسالة والموضع فقط (يعتمد على المحرك) | ✗ | ✗ | التحليل الافتراضي، بيانات API |
jsonc-parser |
offset دقيق + رمز الخطأ |
✓ | ✓ (modify + applyEdits) |
المحررات، ملفات الإعداد |
json5 |
معلومات السطر والعمود | ✓ (أكثر تسامحًا) | ✗ | قراءة إعداد JSON5 |
jsonlint |
معلومات السطر والعمود | ✗ | ✗ | للمرجع فقط، غير مصان نشطًا |
jsonpath-plus |
أخطاء صياغة التعبير | — | — | الاستعلام بتعبير |
fast-json-patch |
أخطاء على مستوى العملية | — | — | توليد التصحيحات وتطبيقها |
lz-string |
— | — | — | ضغط JSON داخل URL |
تختلف رسائل خطأ JSON.parse اختلافًا كبيرًا بين المحركات. ينتج V8 شيئًا مثل
Unexpected token } in JSON at position 42، لكن دقة الموضع تعتمد على إصدار المحرك؛
بينما يعيد jsonc-parser بنية مستقرة { error, offset, length }، وهي مناسبة لعلامات المحرر.
3. أربع نقاط قرار رئيسية
3.1 هل تحتاج إلى الإزاحات
إن كنت تبني محررًا وتريد "انقر الخطأ لتنتقل إلى السطر المقابل"، فأنت بحاجة إلى إزاحة. الاختبار بسيط: إن كانت رسالة خطئك لا تطبع سوى "JSON غير صالح"، فسيتعين على المستخدمين البحث بأنفسهم.
import { parse, printParseErrorCode } from 'jsonc-parser';
const errors: Array<{ error: number; offset: number; length: number }> = [];
parse(text, errors, { allowTrailingComma: true, disallowComments: false });
if (errors.length > 0) {
const firstError = errors[0];
console.error(`${printParseErrorCode(firstError.error)} at offset ${firstError.offset}`);
}
3.2 هل تحتاج إلى الحفاظ على النص الأصلي
لقراءة القيم فقط → أي محلل يكفي. "غيّر حقلًا واحدًا وأبقِ كل شيء آخر كما كان" → يجب أن تستخدم واجهة API تحريرية، لا "حلّل → غيّر الكائن → سلسل".
هذا الأخير يفقد: التعليقات، وترتيب المفاتيح (في بعض التنفيذات)، ونمط الإزاحة البادئة، وصياغة الأعداد الحرفية (1e3 يصبح 1000)، وأشكال الهروب (\u4e2d يصبح المحرف الفعلي).
3.3 هل سلوكيات الحدود صريحة
قبل اختيار مكتبة، تحقق من التوثيق في ثلاثة أمور:
- كيف تُعالج المفاتيح المكررة (احتفظ بالأخير / ارمِ خطأً)؛
- هل تفقد الأعداد الصحيحة الكبيرة دقتها (معظم مكتبات JS تفعل، لأنها تمر كلها عبر
Number)؛ - النطاق المدعوم لـ BOM والتعليقات والفواصل الزائدة.
إن لم يكن هناك توثيق، فاكتب عينة صغيرة واختبرها بنفسك. هذا أكثر موثوقية من قراءة README.
3.4 حالة الصيانة
خطر مكتبة JSON ليس نقص الميزات، بل الإهمال طويل الأمد: لن يقدم أحد تصحيحات أمنية (تلوث النموذج الأولي، ReDoS) بعد الآن.
4. مقارنة مع لغات أخرى
| اللغة | المكتبة القياسية / السائدة | الفرق الجوهري |
|---|---|---|
| JavaScript | JSON.parse |
كل الأعداد بدقة مزدوجة |
| TypeScript | كما سبق + jsonc-parser / zod |
الأنواع موجودة في وقت الترجمة فقط |
| Go | encoding/json |
float64 افتراضيًا، استخدم UseNumber() للحفاظ على الدقة؛ json.RawMessage للتحليل المؤجل |
| Java | Jackson / Gson / Moshi | مع Jackson، انتبه لخطر تفعيل الكتابة الافتراضية |
| Python | json / orjson |
parse_float=Decimal يحفظ الدقة؛ orjson أسرع لكنه لا يدعم كل الأنواع |
| Rust | serde_json |
إلغاء تسلسل قوي الأنواع؛ ميزة arbitrary_precision تحفظ الدقة |
| C++ | simdjson / RapidJSON | SIMDJSON يستهدف إنتاجية التحليل، وRapidJSON أعمّ استخدامًا |
عند تبادل البيانات بين اللغات، يبقى أسهل ما يعثر عليه المرء هو دقة الأعداد وصيغ الوقت؛ واختيار المكتبة يخففها لا يلغيها.
5. التوليفات النموذجية
الخيار 1: موقع أدوات (جانب المتصفح)
Parsing and error location: jsonc-parser
Editor: CodeMirror 6 + @codemirror/lang-json
Query: jsonpath-plus
Patch: fast-json-patch
Share links: lz-string
السمة المميزة لهذا التوليف أن كل شيء يعمل محليًا ولا تُرفع أي بيانات، ما يوافق توقعات الخصوصية لموقع أدوات.
الخيار 2: بوابة API على الخادم
Validation: Ajv (compile the schema once, reuse it)
Parsing: native JSON.parse (together with a body size limit)
Deferred parsing of large fields: keep the raw string, parse only when needed
لا تُدخل مكتبات الاستعلام/التصحيح إلى طبقة البوابة لتنفيذ منطق العمل — فهذه مهمة طبقة العمل.
الخيار 3: CLI والسكربتات
Pick fields: jq
Format conversion: yq / dasel
Interactive browsing: jless
Batch validation: ajv-cli
6. الأثر الحقيقي لحجم الحزمة والأداء
jsonc-parserصغير جدًا ومناسب للحزمة الرئيسية؛json5أكبر قليلًا منjsonc-parserلأنه يدعم صياغة أكثر؛jsonpath-plusيتضمن تقييم التعبيرات وهو أكبر ملحوظًا، فينبغي تحميله كسولًا لكل صفحة؛fast-json-patchمتوسط الحجم ولا يلزم إلا عند وجود ميزة مقارنة.
التحسين مباشر: استورد ديناميكيًا لكل صفحة، ولا تضعها في حزمة الشاشة الأولى.
const { JSONPath } = await import('jsonpath-plus');
7. قائمة الفحص
- [ ] اختر المكتبات بحسب الغرض؛ لا تستخدم مكتبة استعلام للتحليل؛
- [ ] استخدم
jsonc-parserعند الحاجة إلى مواقع خطأ دقيقة؛ - [ ] استخدم واجهات API التحريرية عندما يجب الحفاظ على التعليقات والتنسيق؛
- [ ] اختبر سلوكيات الحدود الثلاث عمليًا: المفاتيح المكررة والأعداد الصحيحة الكبيرة وBOM؛
- [ ] راقب حالة صيانة المكتبة والتنبيهات الأمنية؛
- [ ] استورد المكتبات الكبيرة ديناميكيًا عند الحاجة.
الأسئلة الشائعة
كيف أختار مكتبة JSON بحسب حجم مشروعي؟
الأدوات الصغيرة التي تقرأ بيانات API فقط يمكنها البقاء على JSON.parse الأصلي. المشاريع التي تحتاج مواقع خطأ بمستوى المحرر أو يجب أن تحفظ التنسيق الأصلي تستخدم jsonc-parser. تحتاج بوابة الخادم إلى التحقق والتحليل فقط، وتُترك مكتبات الاستعلام والتصحيح لطبقة العمل، بينما تستطيع سكربتات CLI استخدام jq وyq وajv-cli مباشرة.
لماذا تهم حالة الصيانة أكثر من عدد الميزات؟
الخطر الحقيقي لمكتبة JSON هو الإهمال طويل الأمد لا نقص الميزات: لن يقدم أحد تصحيحات أمنية لتلوث النموذج الأولي أو ReDoS. ومهما كانت قائمة الميزات كاملة، فإن مكتبة متوقفة تتركك تصححها بنفسك. عامل الصيانة والتنبيهات الأمنية كمعايير صلبة بدلًا من مقارنة جداول الميزات.
هل أستخدم JSON.parse لتغيير حقل واحد مع الحفاظ على التعليقات والإزاحة؟
لا. التحليل ثم تغيير الكائن ثم التسلسل يفقد التعليقات وترتيب المفاتيح ونمط الإزاحة وصياغة الأعداد الحرفية (1e3 يصبح 1000) وأشكال الهروب (\u4e2d يصبح المحرف الفعلي). تغيير حقل واحد مع إبقاء ما سواه سليمًا يتطلب واجهة API تحريرية مثل modify وapplyEdits في jsonc-parser.