منسّق JSON
جمّل JSON بمسافتين أو أربع مسافات أو علامة جدولة، أو صغّره إلى سطر واحد، وشاهد رقم السطر والعمود بالضبط عند أي خطأ في التحليل.
سيظهر الإخراج هنا
ما الذي يفعله منسّق JSON هذا
JSON (JavaScript Object Notation) هو الصيغة الأكثر شيوعًا لنقل البيانات المهيكلة بين البرامج — استجابات واجهات البرمجة، وملفات الإعداد، وأسطر السجلات وغيرها. صُمّم ليكون مضغوطًا، وهو ما يجعله أيضًا صعب القراءة عندما تتداخل الكائنات عدة مستويات أو تصل في سطر واحد. تأخذ هذه الأداة أي JSON تلصقه وتعيد كتابته بطريقتين: مُجمَّلًا، بمسافات بادئة متسقة كي تتضح البنية بنظرة واحدة، أو مُصغَّرًا، خاليًا من كل مسافة اختيارية ليكون أصغر ما يمكن عند الإرسال.
كما يتحقّق من الصحة أثناء التنسيق. ولأنه يحلّل النص قبل إعادة تسلسله، فإن JSON غير الصالح لا ينتج مخرجات مضللة أبدًا — بل تحصل على السطر والعمود حيث فشل التحليل، حيثما أمكنه استنتاجهما، لتنتقل مباشرة إلى المشكلة.
التجميل مقابل التصغير — متى تستخدم كلًا منهما
للوضعين هدفان متعاكسان، ومعظم سير العمل يستخدم كليهما في مراحل مختلفة:
- جمّل عندما تقرأ أو تصحّح الأخطاء: فحص استجابة واجهة برمجة، أو مقارنة حمولتين، أو مراجعة ملف إعداد في طلب سحب. المسافات البادئة تحوّل جدار النص إلى شجرة يسهل تصفحها.
- صغّر عندما ترسل: تضمين JSON داخل HTML، أو تخزينه في ملف تعريف ارتباط أو ذاكرة تخزين مؤقت، أو إرساله في جسم طلب حيث يهمّ كل بايت. JSON المصغَّر هو نفس البيانات تمامًا، لكن بلا مسافات.
محدِّد المسافة البادئة (مسافتان، أو 4 مسافات، أو Tab) يؤثر فقط على المخرجات المجمَّلة. المسافتان هما العُرف الأكثر شيوعًا في JavaScript وأدوات الويب؛ وأربع مسافات أو علامات جدولة تناسب الفرق التي تفضّلها. أيًا كان اختيارك، تبقى النتيجة JSON صالحًا — فالمسافة البادئة شكلية بحتة.
قراءة أخطاء التحقق
عندما يكون JSON غير صالح، تُبلغ الأداة عن سطر وعمود أول مشكلة بدل «غير صالح» المجرّدة — إلا في الحالة الوحيدة التي يصفها القسم الخاص بالمكان الذي يشير إليه السطر والعمود. تختلف رسائل أخطاء المحركات بين المتصفحات وغالبًا ما تُغفل الموضع، لذا يُحسب الموقع بشكل مستقل ويشير إلى نقطة معقولة للبدء منها. أصلح الخطأ الأول ثم أعد الفحص — فحرف واحد في غير موضعه يتسبّب غالبًا في عدة مشكلات ظاهرية.
أخطاء JSON الشائعة
يُعدّ JSON أكثر صرامة من كائنات JavaScript الحرفية التي يشبهها. وهذه هي الأخطاء التي توقع الناس أكثر من غيرها:
- الفواصل النهائية: الفاصلة بعد آخر عنصر في كائن أو مصفوفة صالحة في JavaScript لكنها غير صالحة في JSON.
- علامات الاقتباس المفردة: يجب أن تستخدم سلاسل JSON ومفاتيحه علامات اقتباس مزدوجة. 'قيمة' غير صالحة؛ "قيمة" صحيحة.
- مفاتيح بلا علامات اقتباس: كل مفتاح كائن يجب أن يكون سلسلة بين علامتي اقتباس، لذا يجب أن يتحوّل { name: "x" } إلى { "name": "x" }.
- التعليقات: لا يملك JSON صياغة للتعليقات. الرمزان // و/* */ سيسبّبان خطأ تحليل.
- أرقام خاصة: NaN وInfinity و-Infinity ليست أرقام JSON صالحة.
- علامات اقتباس خاطئة: «علامات الاقتباس الذكية» المنسوخة من معالج نصوص تبدو كعلامات اقتباس لكنها أحرف مختلفة ولن تُحلَّل.
إلى أين يشير السطر والعمود المُبلَّغ عنهما
الموضع ليس المكان الذي أسقطت فيه شيئًا، بل المكان الذي التقى فيه المحلّل أول مرة بشيء لا يجوز وجوده هناك، وهما في العادة مكانان مختلفان. في الكائن أدناه يفتقر السطر 3 إلى الفاصلة التي كان يجب أن تُنهيه، وتُبلغ الأداة عن السطر 4، العمود 3: علامة الاقتباس التي تفتح المفتاح التالي. لم يكن شيء خاطئًا حتى وصلت تلك العلامة، لأن الوثيقة كان يجوز أن تنتهي بعد السطر 3؛ فلا يعلم المحلّل بالإسقاط إلا حين يلتقي بشيء ليس فاصلة ولا قوسًا مغلقًا.
{
"id": 42,
"name": "widget"
"price": 9.99
}- الفاصلة الناقصة يُبلَّغ عنها عند أول حرف من كل ما يأتي بعدها، وهو في JSON ذي المسافات البادئة كما أعلاه السطر التالي: فاقرأ السطر المذكور مع السطر الذي فوقه.
- الفاصلة الزائدة يُبلَّغ عنها عند القوس المغلق: السطر 3، العمود 1 لكائن يقع زوجه الأخير في السطر 2. الفاصلة تَعِد بزوج آخر، والقوس هو ما ينقض الوعد.
- السلسلة غير المغلقة يُبلَّغ عنها في الغالب في نهاية السطر الذي فُتحت فيه لا عند علامة الاقتباس الافتتاحية، لأن علامة الاقتباس التالية في سطر لاحق قد تغلقها في مكان آخر. فلا يجوز أن يظهر فاصل سطر داخل سلسلة JSON، فيكون الفاصل أول حرف لا يجوز وجوده هناك.
- السطر 1، العمود 1 في وثيقة تبدو سليمة تمامًا يعني في الغالب علامة ترتيب البايتات. بعض المحرّرات تكتب واحدة عند الحفظ بترميز UTF-8؛ وهي غير مرئية، وتقع قبل القوس الافتتاحي، ولا مكان لها في JSON.
وحيث لا تستطيع الأداة استنتاج أي موضع، تُبلغ عن الفشل بلا موضع بدلًا من ذكر إحداثي مُخمَّن. فسطر وعمود يُذكران بثقة ويشيران إلى صياغة سليمة تمامًا سيدفعانك إلى البحث في المكان الخطأ، وهذا أسوأ من أن تعرف فقط أن الوثيقة لا تُحلَّل.
ما يغيّره التنسيق وما يحفظه
في كل وثيقة تقريبًا يكون الجواب: المسافات ولا شيء غيرها. لكن الأداة لا تحرّر نصك، بل تحلّله إلى قيم حقيقية ثم تكتب تلك القيم من جديد، وخمسة أشياء لا تصمد في رحلة الذهاب والعودة هذه. وليس أيٌّ منها عيبًا في الأداة — فكل واحد منها هو ما تقوله مواصفة JSON عن الرقم أو الكائن — ويجدر معرفة كل واحد قبل أن تلصق المخرجات فوق نصك الأصلي.
- المفتاح نفسه مكتوبًا مرتين: لا يصمد إلا الأخير منهما، لأن الكائن لا يحمل مفتاحًا واحدًا مرتين. ويقول RFC 8259 إن البرمجيات التي تتلقّى كائنًا بأسماء مكرّرة تتصرّف على نحو لا يمكن توقّعه، وقد يُبقي محلّل آخر الأول، فأيّ المفتاحين يبقى لك ليس أمرًا يُعتمد عليه أيضًا.
- عدد صحيح أطول من خمسة عشر رقمًا: تُقرأ أرقام JSON كأعداد فاصلة عائمة مزدوجة الدقة، وهي تحفظ بدقة كل عدد صحيح حتى اثنين مرفوعًا إلى القوة ثلاثة وخمسين — وهو عدد من ستة عشر رقمًا — فيصمد العدد ذو الخمسة عشر رقمًا دائمًا، وقد لا يصمد الأطول منه. الصق 12345678901234567890 فيخرج 12345678901234567000. ومعرّفات قواعد البيانات الطويلة هي الضحية المعتادة: أبقِها سلاسل إن استطعت.
- تُطبَّع صور الأُس والأصفار النهائية: 1e3 تعود 1000، و1.50 تعود 1.5. وهو العدد نفسه مكتوبًا بالصورة القياسية.
- أي مقدار خارج ما يحمله ذلك التمثيل يعود شيئًا آخر: فليس لـ1e400 قيمة بدقة مزدوجة وتعود null، و1e-400 تعود 0. والكسر العشري الطويل يُقرَّب إلى الدقة التي يملكها التمثيل، كما يُقرَّب العدد الصحيح الطويل.
- تسلسل الهروب يصير الحرف الذي يمثّله: \u00e9 تعود é، والزوج البديل المهروب يعود الرمز التعبيري الذي يهجّئه. وهما لأي محلّل السلسلة نفسها؛ إحدى الصورتين أقصر من الأخرى فحسب.
ويُحفظ ترتيب المفاتيح كما كتبته، مع استثناء واحد يجدر معرفته: المفتاح المكوَّن من أرقام فقط، والذي يُقرأ عددًا صحيحًا غير سالب بسيطًا أقل من نحو أربعة مليارات، يُعدّ فهرس مصفوفة فيعود إلى مقدمة كائنه بالترتيب العددي، أينما وضعته. ولا يتحرّك شيء آخر: فلا مفتاح آخر يُعاد ترتيبه، ولا مفتاح يُضاف أو يُعاد تسميته. وإن كان أي من هذا يهمّك، فصغّر بدلًا من أن تُجمّل وقارن النتيجة بنصك الأصلي حرفًا حرفًا؛ فهذا أقصر طريق لترى ما فعلته رحلة الذهاب والعودة.
حين يكون JSON الذي تريده داخل سلسلة
سجلات webhook، وطوابير الرسائل، وأعمدة قواعد البيانات كثيرًا ما تحمل وثيقة JSON كاملة كقيمة سلسلة واحدة، وقد هُرِبت كل علامة اقتباس داخلها. والوثيقة الخارجية صالحة تمامًا، فتجمّلها الأداة وتُبلغ بأنها صالحة — ويبقى الجزء الذي جئت لقراءته سطرًا طويلًا من الشرطات المائلة العكسية. لم يُخطئ شيء: هما وثيقتان، إحداهما ملفوفة داخل سلسلة من الأخرى.
{
"event": "order.created",
"payload": "{\"id\":42,\"total\":19.99}"
}ولذلك تحتاج قراءتها إلى مرحلتين. جمّل الوثيقة الخارجية هنا، وانسخ ما بين علامتي اقتباس السلسلة التي تريدها، وأزل الهروب، ثم الصق النتيجة من جديد. وأداة هروب نصوص JSON تنجز هذه الخطوة الوسطى: فاتجاه فك الهروب فيها يحوّل الشرطة المائلة العكسية وعلامة الاقتباس بعدها إلى علامة اقتباس مزدوجة وحدها، ويحوّل السطر إلى وثيقة تستطيع هذه الصفحة تنسيقها. وإن كنت تتحكّم بما أنتج الملف فالإصلاح الأفضل أعلى من ذلك: أرسل الحمولة كائنًا متداخلًا لا سلسلة، فلا تحتاج إلى أي مرحلة.
كائن واحد في كل سطر ليس وثيقة واحدة
ملفات السجلات، ومخرجات واجهات البرمجة، ونقاط النهاية المتدفّقة تحمل عادةً كائن JSON كاملًا في كل سطر؛ ويُسمّى هذا التنسيق JSON Lines أو NDJSON. وكل سطر منه JSON صالح بذاته، لكن الملف ليس وثيقة JSON، لأن وثيقة JSON تحمل قيمة واحدة بالضبط في المستوى الأعلى، وهذا الملف يحمل عدة قيم، واحدة بعد الأخرى ولا شيء يجمعها.
{"level":"info","msg":"started"}
{"level":"warn","msg":"retrying"}
{"level":"error","msg":"gave up"}الصق ذلك هنا فتُبلغ الأداة عن السطر 2، العمود 1: انتهى الكائن الأول نظيفًا، ثم بدأ ثانٍ حيث كان يجب أن تنتهي الوثيقة. ومن هناك طريقان. نسّق سطرًا واحدًا في كل مرة، وهو ما تريده حين تقرأ مدخلة سجل واحدة. أو اجعل الملف وثيقة واحدة — لُفّ الأسطر بقوسين معقوفين وضع فاصلة في نهاية كل سطر إلا الأخير — وهو ما تريده حين تكون على وشك تحميل الكل في شيء يتوقّع مصفوفة.
الأسئلة الشائعة
- هل يُرسَل JSON الخاص بي إلى خادم؟
- لا. التحليل والتحقق والتنسيق تجري كلها في متصفحك باستخدام JavaScript. لا شيء تلصقه يُرفَع أو يُخزَّن أو يُسجَّل، لذا فاستخدامه آمن مع الحمولات الحساسة.
- هل يغيّر التنسيق بياناتي؟
- في كل وثيقة تقريبًا: لا. فالتجميل والتصغير لا يضيفان أو يزيلان إلا المسافات بين الرموز، وتعود المفاتيح والقيم والبنية متطابقة. لكن هناك استثناءات، كلها نتيجة تحليل نصك إلى قيم حقيقية قبل إعادة كتابته، والقسم الخاص بما يغيّره التنسيق يسردها جميعًا.
- لماذا يعيد ترتيب أرقامي أو تنسيقها؟
- تحلّل الأداة JSON إلى قيم حقيقية ثم تعيد تسلسلها، فتُطبَّع الأرقام إلى صورتها المعيارية (مثلًا 1e3 تصبح 1000). ولأي رقم تحفظه الفاصلة العائمة مزدوجة الدقة بدقة، لا تتغيّر القيمة وتصبح صورتها النصية قياسية فقط. أما الرقم الذي يطلب دقة أو مدى أكبر مما يملكه ذلك التمثيل — عدد صحيح يزيد على خمسة عشر رقمًا، أو كسر عشري طويل، أو مقدار خارجه تمامًا — فالقيمة نفسها تتحرّك، والقسم الخاص بما يغيّره التنسيق يبيّن كيف.
- هل يستطيع التعامل مع ملفات JSON كبيرة جدًا؟
- يستطيع التعامل مع حمولات كبيرة، لكن بما أن كل شيء يعمل في المتصفح، فقد تكون الملفات الضخمة جدًا (عشرات الميغابايتات) بطيئة أو تبلغ حدود الذاكرة حسب جهازك.
- هل يحافظ على ترتيب مفاتيح الكائن؟
- في الغالب نعم: يُحفظ ترتيب المفاتيح تمامًا كما يظهر في مدخلاتك، ولا تفرز الأداة شيئًا من تلقاء نفسها. والاستثناء الوحيد هو المفتاح المكوَّن من أرقام فقط والذي يُقرأ عددًا صحيحًا غير سالب بسيطًا أقل من نحو أربعة مليارات؛ فهذا يُعدّ فهرس مصفوفة ويعود إلى مقدمة كائنه بالترتيب العددي. ويصف JSON الكائن بأنه مجموعة غير مرتّبة، فلا يُكسر شيء، لكنه يفاجئ؛ والقسم الخاص بما يغيّره التنسيق يحمل التفصيل.
- ما الفرق بين JSON وكائن JavaScript؟
- JSON صيغة نصية لتبادل البيانات؛ أما كائن JavaScript فقيمة في الذاكرة. JSON أكثر صرامة: يشترط مفاتيح وسلاسل بين علامتي اقتباس مزدوجتين، ويمنع الفواصل النهائية والتعليقات، ولا يسمح إلا بمجموعة ثابتة من أنواع القيم (سلاسل، أرقام، قيم منطقية، null، مصفوفات وكائنات).
- هل يمكنني تنسيق JSON5 أو JSONC (JSON مع تعليقات)؟
- لا. تتحقّق هذه الأداة من JSON القياسي الصارم. ويضيف JSON5 وJSONC تعليقات وتسهيلات أخرى ليست جزءًا من مواصفة JSON، لذا سيتم الإبلاغ عنها كأخطاء.
- هل السلسلة أو الرقم JSON صالح بذاته؟
- نعم. وثيقة JSON هي أي قيمة واحدة، فـ"مرحبًا" و42 وtrue وnull كل منها كامل وصالح، وهذه الأداة تنسّق الأربعة. ولم يكن الأمر كذلك دائمًا: فقد كان RFC 4627 (2006) يشترط كائنًا أو مصفوفة في المستوى الأعلى، وخفّف RFC 7159 ذلك في 2014، ويحمل RFC 8259 القاعدة الأوسع اليوم. وكل ما يرفض قيمة مجرّدة فهو يتبع المواصفة الأقدم.
- هل يمكنني تنسيق JSON Lines أو NDJSON هنا؟
- سطرًا واحدًا في كل مرة: نعم، فكل سطر وثيقة JSON كاملة. أما الملف كله في مرة واحدة: فلا، لأنه عدة وثائق لا وثيقة واحدة، وتُبلغ الأداة عن السطر 2، العمود 1، حيث تبدأ الثانية. والقسم أعلاه عن كائن واحد في كل سطر يغطّي المخرجين.
- لماذا يُبلَّغ عن السطر 1، العمود 1 في وثيقة تبدو صحيحة؟
- في الغالب بسبب حرف غير مرئي قبل القوس الافتتاحي، وفي الغالب بسبب علامة ترتيب بايتات تركها محرّر عند الحفظ بترميز UTF-8. وهو حرف حقيقي، ولا يمكن رؤيته، ولا مكان له في JSON. أعد حفظ الملف بترميز UTF-8 بلا علامة ترتيب بايتات، أو احذف أول حرف والصق من جديد.
- هل يُسقِط التنسيق مفتاحًا مكرّرًا؟
- نعم، وهي الحالة الوحيدة التي تحمل فيها المخرجات أقل من المدخلات. فالمفتاح المكتوب مرتين في الكائن نفسه لا يُبقي إلا الأخير منهما، لأن الأداة تحلّل نصك إلى قيم حقيقية والكائن لا يحمل مفتاحًا واحدًا مرتين. وأيّ المفتاحين يصمد ليس أمرًا منقولًا كذلك: فـRFC 8259 يقول إن البرمجيات التي تتلقّى كائنًا كهذا تتصرّف على نحو لا يمكن توقّعه، وقد يُبقي محلّل آخر الأول.
أدوات ذات صلة
- هروب نصوص JSON
هروب النص ليصلح داخل سلسلة JSON، أو إعادة نص هارب إلى ما يقوله.
- مقارنة JSON
قارن مستندَي JSON — ترتيب المفاتيح والتنسيق لا يُحتسبان.
- منسّق SQL
ينسّق SQL ويجمّله — بعدة لهجات.
- منسّق XML
ينسّق XML ويتحقّق منه — تجميل أو تصغير.