FlowingDev

شرح JSON: صيغة البيانات التي تدير الويب بصمت

تعرّف على ماهية JSON (JavaScript Object Notation)، ولماذا هي الصيغة المهيمنة لتبادل البيانات، وكيف تعمل بنيتها النصية البسيطة.

جرّب الأداة: محرر JSON

في جملة واحدة

JSON هي صيغة خفيفة ومبنية على النص لهيكلة وتبادل البيانات، سهلة القراءة للبشر وسهلة التحليل (parsing) للآلات.

المشكلة التي يحلها

في الأيام الخوالي للويب (أواخر التسعينيات وأوائل الألفينات)، إذا أردت لموقعك أن يجلب بيانات جديدة بدون إعادة تحميل الصفحة بالكامل، فغالبًا كنت تستخدم تقنية تُدعى AJAX (Asynchronous JavaScript and XML). وكما يوحي الاسم، كانت صيغة البيانات المفضلة هي XML.

لغة XML قوية، لكنها أيضًا... مطوّلة. وضخمة. مليئة بالوسوم الافتتاحية والختامية والخصائص ومساحات الأسماء. وكان تحليلها (parsing) في JavaScript، لغة المتصفح، مهمة شاقة. كان عليك التنقل في شجرة مستندات معقدة، وببساطة لم تكن تبدو طبيعية في التعامل معها.

<!-- هذا مجرد مستخدم واحد. تخيل قائمة بالآلاف. يا للهول. -->
<user id="123">
  <username>coder_dave</username>
  <isActive>true</isActive>
  <roles>
    <role>admin</role>
    <role>editor</role>
  </roles>
</user>

حوالي عام 2001، كان مطور اسمه دوغلاس كروكفورد يعمل على مشروع واحتاج طريقة أبسط لتمرير البيانات إلى المتصفح. وتوصل إلى إدراك عبقري: JavaScript لديها بالفعل طريقة ممتازة لتمثيل هياكل البيانات — وهي صيغة كائنها الحرفية (object literal syntax). ماذا لو كان بإمكانك إرسال البيانات كنص يبدو تمامًا مثل كائن JavaScript؟

كانت هذه ولادة JSON (JavaScript Object Notation). يمكن للخادم إرسال هذا النص:

{
  "id": 123,
  "username": "coder_dave",
  "isActive": true,
  "roles": ["admin", "editor"]
}

...ويمكن للمتصفح، بأقل مجهود، تحويله إلى كائن JavaScript أصلي يمكنه التعامل معه على الفور. كانت صيغة خفيفة، نظيفة، ومناسبة تمامًا للغة الويب الأم. هذه البساطة تسببت في انفجار كامبري في واجهات برمجة التطبيقات (APIs)، مما أدى إلى صعود تطبيقات الصفحة الواحدة الديناميكية، والواجهات الخلفية لتطبيقات الجوال، وتقريبًا كل الإنترنت الحديث كما نعرفه. JSON لم يحل مشكلة تقنية فحسب؛ بل مهّد الطريق لجيل جديد كامل من البرمجيات.

كيف يعمل من الداخل

في جوهره، JSON هو مجرد مجموعة من القواعد لكتابة البيانات كنص. القواعد بسيطة، وهذا هو بالضبط سبب نجاحه الباهر.

لبنات البناء: المفاتيح والقيم

عالم JSON بأكمله مبني على بنية بسيطة واحدة: زوج المفتاح-القيمة.

"key": value

  • المفتاح هو دائمًا نص (string)، محاط بعلامتي اقتباس مزدوجتين. هذا الأمر غير قابل للتفاوض.
  • القيمة يمكن أن تكون واحدة من عدة أنواع بيانات محددة.

هذا الزوج يصف معلومة واحدة، مثل "name": "Luke Skywalker" أو "age": 19.

أنواع البيانات

JSON صارم بشأن أنواع قيمه. لا يمكنك وضع أي شيء هناك. لديك ستة أنواع أساسية بالإضافة إلى null.

النوع مثال الوصف
نص (String) "The force is strong with this one." أي نص. يجب أن يكون بين علامتي اقتباس مزدوجتين.
رقم (Number) 1138 أو 3.14 أعداد صحيحة أو أرقام الفاصلة العائمة. لا يوجد تمييز بينهما.
قيمة منطقية (Boolean) true أو false دائمًا بأحرف صغيرة. يمثل حالة ثنائية.
مصفوفة (Array) ["Tatooine", "Dagobah", "Bespin"] قائمة مرتبة من القيم، محاطة بـ [].
كائن (Object) { "weapon": "lightsaber", "color": "green" } مجموعة غير مرتبة من أزواج المفتاح-القيمة، محاطة بـ {}.
Null null يمثل الغياب المتعمد لقيمة.

هذا كل شيء. لاحظ ما هو مفقود: الدوال، التواريخ (تُرسل كنصوص)، undefined، والأشهر من ذلك كله، التعليقات. هذه البساطة الشديدة هي ميزة، وليست علّة (bug)؛ فهي تحافظ على الصيغة واضحة وسهلة التحليل (parsing) لأي لغة برمجة.

هيكلة البيانات: الكائنات والمصفوفات

القوة الحقيقية تأتي من تداخل هذه الأنواع. يمكن أن تكون value في زوج المفتاح-القيمة كائنًا آخر أو مصفوفة. هذا يتيح لك بناء هياكل بيانات معقدة بشكل لا نهائي.

الكائنات ({...}) تُستخدم لتجميع البيانات ذات الصلة حول "شيء" واحد. فكر فيها كمدخل في قاموس أو ملف شخصي.

المصفوفات ([...]) تُستخدم للقوائم المرتبة من العناصر. يمكن أن تكون العناصر في مصفوفة من أي نوع، حتى لو كانت مختلطة (على الرغم من أنه من الممارسات الجيدة عادةً إبقاؤها موحدة).

لنلقِ نظرة على مثال أكثر اكتمالاً:

{
  "squadName": "Star Wars Heroes",
  "formed": 1977,
  "active": true,
  "members": [
    {
      "name": "Luke Skywalker",
      "age": 19,
      "secretIdentity": null,
      "powers": [
        "Jedi mind tricks",
        "Piloting",
        "The Force"
      ]
    },
    {
      "name": "Han Solo",
      "age": 29,
      "secretIdentity": null,
      "powers": [
        "Blaster accuracy",
        "Sarcasm",
        "Kessel Run under 12 parsecs"
      ]
    }
  ]
}

هل رأيت؟ لدينا كائن خارجي يصف الفرقة. إحدى خصائصه، "members"، هي مصفوفة. كل عنصر في تلك المصفوفة هو كائن آخر، يمثل بطلاً واحدًا. وكل كائن بطل له خصائصه الخاصة، إحداها ("powers") هي مصفوفة أخرى من النصوص. هكذا تبني شجرة بيانات باستخدام JSON.

من نص إلى كائن: التحليل (Parsing)

الخدعة السحرية هي تحويل هذا النص إلى شيء يمكن للبرنامج استخدامه.

  1. التسلسل (Serialization): تطبيق من جانب الخادم (مكتوب بلغة Python، Java، Go، إلخ) لديه بيانات في الذاكرة. يستخدم مكتبة JSON لعمل serialize لهذه البيانات إلى نص بصيغة JSON. في JavaScript، هذا هو JSON.stringify().
  2. الإرسال: يتم إرسال هذا النص عبر الشبكة، عادةً كجسم (body) لاستجابة HTTP.
  3. التحليل (Parsing): يستقبل العميل (مثل متصفح الويب) هذا النص. ويستخدم محلل JSON مدمجًا لتحويل النص مرة أخرى إلى بنية بيانات أصلية يمكنه التعامل معها. في JavaScript، هذا هو JSON.parse().

هذه العملية المكونة من خطوتين، stringify و parse، هي نبض اتصالات الويب الحديثة.

قصص من الواقع

تطبيق الجوال المليء بالأخطاء

أطلقت شركة ناشئة تطبيق طلبات عبر الجوال لسلسلة مطاعم محلية. في صباح أحد الأيام، بدأ التطبيق في الانهيار لكل مستخدم فور فتحه. كان فريق المطورين في حالة هلع قصوى. أظهرت سجلات الخادم أن الـ API كان يرسل حالة 200 OK، والبيانات بدت سليمة عند إلقاء نظرة سريعة عليها. بعد ساعات من تصحيح الأخطاء المحموم، فحصوا أخيرًا النص الخام لاستجابة الـ API. مطور في الواجهة الخلفية، في محاولة للمساعدة، كان قد أضاف ملاحظة لزملائه مباشرة في الكود الذي يولد الـ JSON: // TODO: Confirm weekend hours. تم تضمين هذا التعليق في نص JSON النهائي. على الرغم من أنه غير ضار في الكود، إلا أن التعليق يجعل JSON غير صالح. رأى محلل JSON الصارم في التطبيق الرمز // غير المتوقع وفشل على الفور، مما أدى إلى انهيار التطبيق حتى قبل أن يتمكن من عرض رسالة خطأ.

الدرس: محللات (parsers) JSON لا ترحم. الصيغة محددة بصرامة لسبب: ضمان التوافقية التشغيلية. حرف واحد غير صالح — تعليق، فاصلة زائدة في النهاية، علامة اقتباس مفردة — سيؤدي إلى رفض المحلل الصالح للحمولة بأكملها.

كارثة التسعير الدولية

كانت شركة تجارة إلكترونية أمريكية تتوسع في ألمانيا. أرسلت واجهة برمجة التطبيقات (API) الخاصة بها معلومات المنتج بصيغة JSON، بما في ذلك حقل price. لمنتج بقيمة 19.95 دولارًا، كان الـ JSON هو "price": 19.95. استعدادًا للإطلاق في ألمانيا، قام أحد المطورين بتحديث الواجهة الخلفية لتنسيق السعر وفقًا للتقاليد الألمانية، حيث تُستخدم الفاصلة كفاصل عشري. بدأت الـ API في إرسال "price": "19,95". لكن كود الواجهة الأمامية كان لا يزال يتوقع رقمًا. في JavaScript، parseFloat("19,95") تُقيّم إلى 19 فقط، متجاهلة كل شيء بعد الفاصلة. فجأة، كانت جميع المنتجات في ألمانيا تُعرض بخصم هائل وغير صحيح.

الدرس: JSON مخصص للبيانات الخام، وليس للعرض. نوع البيانات مهم. السعر هو رقم، لذا أرسله كرقم (19.95). دع تطبيق جانب العميل (المتصفح أو تطبيق الجوال) يتولى مهمة تنسيق هذا الرقم إلى $19.95 أو 19,95 € أو ¥19 بناءً على منطقة المستخدم. لا تخلط بين البيانات ومنطق العرض.

ملف الإعدادات الذي لا يمكن شرحه

كان فريق صغير يقوم بإعداد خدمة جديدة باستخدام ملف config.json لتخزين سلاسل اتصال قاعدة البيانات ومفاتيح API وعلامات الميزات (feature flags). مع ازدياد تعقيد الإعدادات، كانوا بحاجة ماسة إلى إضافة تعليقات لشرح ما يفعله كل إعداد غامض ولماذا تم تعيينه إلى قيمة معينة. لكن JSON يمنع التعليقات. كان "حلهم" هو إنشاء ملف config_documentation.md يجب أن يظل متزامنًا مع config.json. سرعان ما أصبح هذا مصدر إزعاج كبير. في النهاية، أدركوا خطأهم.

الدرس: استخدم الأداة المناسبة للمهمة المناسبة. JSON هو البطل بلا منازع لتبادل البيانات بين الآلات (مثل استجابة API). ولكن بالنسبة لملفات الإعدادات التي يديرها البشر حيث تكون التعليقات وسهولة القراءة أمورًا حاسمة، فإن صيغًا أخرى مثل YAML أو حتى ملف .js بسيط غالبًا ما تكون خيارًا أفضل بكثير.

أخطاء وفخاخ شائعة

  • الفواصل الزائدة في النهاية: إضافة فاصلة بعد العنصر الأخير في كائن أو مصفوفة ("key": "value",}) ستجعل JSON الخاص بك غير صالح. هذا خطأ شائع للمطورين المعتادين على الصيغ الأكثر تساهلاً في JavaScript.
  • التعليقات: لا يمكنك استخدامها. // و /* ... */ ليسا جزءًا من المواصفات وسيكسران عملية التحليل. إذا كنت بحاجة إلى إضافة بيانات وصفية، فعليك القيام بذلك داخل بنية البيانات نفسها، على سبيل المثال: { "_comment": "هذه ملاحظتي", "realData": "..." }.
  • علامات الاقتباس المفردة: يجب أن تستخدم جميع المفاتيح وجميع القيم النصية علامات اقتباس مزدوجة ("). استخدام علامات الاقتباس المفردة (') هو JSON غير صالح، على الرغم من شيوعه في JavaScript.
  • المفاتيح غير المعرفة (Undefined): إرسال {"key": undefined} غير ممكن. عادةً ما يتم حذف زوج المفتاح-القيمة أثناء عملية التسلسل (serialization). لتمثيل قيمة مفقودة، استخدم null.
  • استخدام الأرقام كنصوص: بينما يمكنك إرسال رقم كنص (مثل "id": "123"), إلا أنها ممارسة سيئة. فهي تجبر التطبيق المستلم على القيام بعمل إضافي لتحويله مرة أخرى إلى رقم ويمكن أن تؤدي إلى أخطاء دقيقة (على سبيل المثال، "10" > "9" هي false في مقارنة النصوص).

لماذا يجب أن تضعه في حسبانك

إذا كنت تتعامل مع الكود بأي صفة، فسوف تصادف JSON. المسألة ليست إذا، بل متى وكم مرة.

  • مطور الويب: ستستهلك JSON من واجهات برمجة التطبيقات (APIs) وترسله من نماذجك. من المحتمل أن تُدار حالة تطبيقك بالكامل ككائن شبيه بـ JSON.
  • مطور الواجهة الخلفية: ستبني واجهات برمجية تنتج JSON وتستهلك JSON من خدمات أخرى.
  • مطور تطبيقات الجوال: ستتواصل مع الواجهة الخلفية الخاصة بك حصريًا عبر واجهات برمجية تتحدث بـ JSON.
  • مهندسو DevOps/SREs: أدوات البنية التحتية ككود (Infrastructure-as-code)، وخطوط أنابيب CI/CD، وواجهات برمجة التطبيقات لمزودي الخدمات السحابية كلها تُكوَّن وتُدار باستخدام JSON أو صيغ مشابهة.
  • علماء البيانات: ستسحب البيانات من واجهات برمجة التطبيقات على الويب، وستصل دائمًا تقريبًا بصيغة JSON.
  • غير المطورين الفضوليين: فهم بنية المفتاح-القيمة البسيطة لـ JSON يمكن أن يزيل الغموض عن كيفية حصول التطبيقات على هاتفك على بياناتها وكيفية تحميل مواقع الويب للمحتوى ديناميكيًا. إنها نظرة خاطفة تحت غطاء العالم الرقمي.

JSON هي لغة التواصل المشتركة (lingua franca) للبيانات على الإنترنت. معرفة قواعده والغرض منه هي مهارة أساسية لأي شخص يبني أو يعمل مع البرمجيات الحديثة.

تعمق أكثر

  • JSON.org: المواصفة الأصلية المكونة من صفحة واحدة من دوغلاس كروكفورد. درس نموذجي في البساطة.
  • RFC 8259: "المعيار" الرسمي من IETF الذي يضفي الطابع الرسمي على صيغة JSON للإنترنت.
  • MDN: العمل مع JSON: الدليل النهائي لمطوري JavaScript، يشرح JSON.parse() و JSON.stringify().
  • ويكيبيديا: JSON: يقدم نظرة عامة رائعة على التاريخ والمشتقات (مثل GeoJSON) والمقارنات مع الصيغ الأخرى.

انتهينا من النظرية. حان وقت التطبيق — 100% في متصفحك.

جرّب الأداة: محرر JSON