اذهب إلى المحتوى

العمل مع البيانات بصيغة JSON في جافا سكريبت


ابراهيم الخضور

تُعد صيغة جافاسكريبت لترميز الكائنات JavaScript Object Notation واختصارًا JSON صيغة نصية لتمثيل البيانات المهيكلة وفقًا للصياغة الكائنية في جافاسكريبت، وهي شائعة الاستخدام لتمثيل وتبادل المعطيات عبر الويب (مثل إرسال البيانات من الخادم إلى العميل لتُعرض على صفحة الويب). ستصادف هذه الصيغة كثيرًا لهذا سنشرح لك في هذا المقال ما تحتاج معرفته عن عمل JSON في جافاسكربت بما في ذلك تفسير صياغتها للوصول إلى البيانات التي تضمها وكتابة بياناتك الخاصة بهذه الصياغة.

ننصحك قبل أن تبدأ العمل معنا في هذه السلسلة أن تطلع على:

  1. أساسيات HTML.
  2. أساسيات عمل CSS
  3. أساسيات جافاسكربت كما شرحناها في سلسلة المقالات السابقة.
  4. أساسيات البرمجة كائنية التوجه كما شرحناها في مقال أساسيات العمل مع الكائنات في جافا سكريبت.

ماهي صيغة JSON؟

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

لتنسيق JSON طبيعة نصية، وهو أمر مفيد لنقل البيانات عبر الشبكات. وتحتاج إلى تحويل تنسيق JSON إلى كائن جافا سكريبت أصلي إن أردت الوصول إلى محتوياته. وبالطبع، لن يكون اﻷمر صعبًا لوجود كائن JSON عام في جافا سكريبت يقدّم توابع للتحويل بين الصيغتين (JSON - كائن جافا سكريبت).

ملاحظة: تُدعى عملية تحويل كائن إلى نص بغية إرساله عبر شبكة بالسَلسَلة serialization، وعملية تحويل سلسلة نصية إلى كائن أصلي إلغاء السَلسَلة deserialization.

يمكن تخزين نص JSON في ملف خاص، وسيكون على شكل ملف نصي نمطي يحمل اللاحقة json.، وله نمط MIME التالي: application/json.

هيكلية JSON

قلنا سابقًا أن نص JSON هو سلسلة نصية منسقة بطريقة تحاكي كائن جافا سكريبت حرفي. وباﻹمكان إضافة نفس اﻷنواع اﻷساسية للبيانات ضمن تنسيق JSON كما تفعل تمامًا عند التعامل مع كائن جافا سكريبت، مثل النصوص واﻷرقام والمصفوفات والقيم المنطقية وكائنات حرفية أخرى. يتيح لك هذا التنسيق بناء البيانات بشكل هرمي كالتالي:

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
    },
    {
      "name": "Madame Uppercut",
      "age": 39,
      "secretIdentity": "Jane Wilson",
      "powers": [
        "Million tonne punch",
        "Damage resistance",
        "Superhuman reflexes"
      ]
    },
    {
      "name": "Eternal Flame",
      "age": 1000000,
      "secretIdentity": "Unknown",
      "powers": [
        "Immortality",
        "Heat Immunity",
        "Inferno",
        "Teleportation",
        "Interdimensional travel"
      ]
    }
  ]
}

ولو حملّنا النص السابق في برنامج جافا سكريبت وفسرناه إلى كائن يدعى superHeroes مثلًا، سنتمكن من الوصول إلى البيانات التي يضمها وفق أسلوب الوصول إلى أعضاء الكائنات (نقطة أو قوس مربع). إليك مثالًا:

superHeroes.homeTown;
superHeroes["active"];

وللوصول إلى بيانات أعمق في التسلسل الهرمي، عليك كتابة سلسلة بأسماء الخاصيات وأدلة المصفوفات وصولًا إلى الخاصية المطلوبة. فلو أردت الوصول إلى القوة الخارقة الثالثة للبطل الخارق الثاني الموجود في قائمة البيانات، عليك تنفيذ ما يلي:

superHeroes["members"][1]["powers"][2];
  1. نستخدم اولًا اسم المتغير superHeroes..
  2. ندخل بعدها إلى الخاصية members ضمنه، لهذا نستخدم التعليمة ["members"].
  3. تضم الخاصية members مصفوفة كائنات، وعلينا الوصول إلى الكائن الثاني منها لهذا نستخدم الأمر [1].
  4. وضمن الكائن الثاني من المصفوفة، نريد الوصول إلى الخاصية powers، لهذا نستخدم التعليمة ["powers"].
  5. تضم الخاصية powers مصفوفة تحتوي على القوى الخارقة للأبطال، ونريد من بينها الثالثة [2].

ملاحظة: يمكنك الوصول إلى البيانات السابقة بتنسيق JSON ضمن الملف JSONTest.html (ألق نظرة على الشيفرة المصدرية). جرّب أن تحمّل الملف ثم الوصول إلى البيانات ضمن المتغيّر عبر طرفية جافا سكريبت في متصفحك.

المصفوفات وتنسيق JSON

أشرنا سابقًا أن نص JSON يبدو مشابهًا لكائن جافا سكريبت ضمن سلسلة نصية. ويمكننا أيضًا تحويل المصفوفات من وإلى تنسيق JSON. إليك مثالًا عن استخدام صحيح لتنسيق JSON:

[
  {
    "name": "Molecule Man",
    "age": 29,
    "secretIdentity": "Dan Jukes",
    "powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
  },
  {
    "name": "Madame Uppercut",
    "age": 39,
    "secretIdentity": "Jane Wilson",
    "powers": [
      "Million tonne punch",
      "Damage resistance",
      "Superhuman reflexes"
    ]
  }
]

هذه الشيفرة نص JSON صحيح تمامًا، وعليك فقط الوصول إلى أعضاء المصفوفة (في النسخة المفسّرة منه) بأن تبدأ بدليل العنصر الذي تريده من المصفوفة مثل
[0]["powers"][0].

ملاحظات أخرى

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

تطبيق عملي: العمل مع JSON

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

نقطة الانطلاق

أنشئ بداية نسخة عن الملفين heroes.html و style.css على حاسوبك. ويتضمن الملف الثاني بعض تنسيقات CSS البسيطة لتنسيق الصفحة، بينما يضم اﻷول شيفرة HTML بسيطة لجسم الصفحة، إضافة إلى العنصر <script> الذي يضم شيفرة جافا سكريبت التي سنكتبها خلال عملنا على هذا التمرين.

<header>
...
</header>

<section>
...
</section>

<script>
...
</script>

تتوفر بيانات JSON للتمرين ضمن ملف مخصص على جيت-هب، وسنحمّل هذا الملف باستخدام الشيفرة ونستخدم بعض دوال شجرة DOM لعرض البيانات:

01_json-superheroes.png

دوال المستوى اﻷعلى

وهي كالتالي:

async function populate() {
  const requestURL =
    "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json";
  const request = new Request(requestURL);

  const response = await fetch(request);
  const superHeroes = await response.json();

  populateHeader(superHeroes);
  populateHeroes(superHeroes);
}

نستخدم للحصول على بيانات JSON واجهة برمجية تُدعى Fetch تسمح لنا بإرسال طلبات عبر اﻹنترنت للحصول على موارد من الخادم من خلال جافا سكريبت (مثل الصور والنصوص وملفات JSON وحتى مقتطفات من شيفرة HTML). أي بإمكاننا تحديث جزء صغير من محتوى الصفحة بدلًا من اعادة تحميل الصفحة بالكامل.

تستخدم اﻷسطر اﻷربعة اﻷولى من الدالة الواجهة البرمجية Fetch ﻹحضار ملف JSON من الخادم:

  • صرحنا عن المتغير requestURL لتخزين عنوان الملف على جيت-هب.
  • استخدمنا عنوان URL لتهيئة كائن الطلب Request الجديد.
  • أرسلنا طلب عبر اﻹنترنت باستخدام الدالة ()fetch وسيعيد ذلك كائن استجابة Response.
  • نحصل على الاستجابة بتنسيق JSON عن طريق استخدام الدالة ()json العائدة للكائن Response.

ملاحظة: الواجهة البرمجية غير متزامنة asynchronous، لهذا لابد من إضافة الكلمة المحجوزة async قبل اسم الدالة التي تستخدم الواجهة والكلمة المحجوزة await قبل استدعاء أية دوال غير متزامنة.

بعد كل ذلك، سيضم المتغير superHeroes كان جافا سكريبت المبني وفق بيانات JSON. ثم نمرر بعد ذلك الكائن إلى استدعاء دالتين الأولى لتملأ العنصر <header> بالبيانات الصحيحة، والثانية لتنشئ بطاقة معلومات لكل بطل في الفريق ووضعها ضمن العنصر <section>.

ترتيب المعلومات في الترويسة

بعد أن حصلنا على البيانات من الخادم وفق تنسيق JSON وحولناها إلى كائن جافا سكريبت، سنستخدمها عن طريق الدالتين اللتين أشرنا إليهما سابقًا. لهذا أضف الشيفرة التالية التي تمثّل تصريحًا عن دالة تحت الشيفرة الموجودة:

function populateHeader(obj) {
  const header = document.querySelector("header");
  const myH1 = document.createElement("h1");
  myH1.textContent = obj.squadName;
  header.appendChild(myH1);

  const myPara = document.createElement("p");
  myPara.textContent = `Hometown: ${obj.homeTown} // Formed: ${obj.formed}`;
  header.appendChild(myPara);
}

تنشئ الشيفرة السابقة بداية عنصر <h1> باستخدام التابع ()createElement، وأسندنا إلى محتواه قيمة الخاصية squadName التي تعود إلى كائن جافا سكريبت، ثم ألحقنا العنصر ومحتواه بالترويسة مستخدمين التابع ()appendChild. كررنا بعد ذلك نفس الخطوات مع الفقرة النصية، إذ أنشأناها بداية ثم وضعنا فيها المحتوى المناسب وألحقناها بالترويسة. والفرق الوحيد بين الحالتين هو أننا ضبطنا المحتوى النصي للفقرة ليكون مساويًا لقالب مفسّر (أو حرفي) template literal يضم قيمتي الخاصيتين homeTown و formed.

إنشاء بطاقة معلومات البطل الخارق

أضف اﻵن شيفرة الدالة التي تُنشئ وتعرض بطاقة البطل إلى نهاية الشيفرة السابقة كالتالي:

function populateHeroes(obj) {
  const section = document.querySelector("section");
  const heroes = obj.members;

  for (const hero of heroes) {
    const myArticle = document.createElement("article");
    const myH2 = document.createElement("h2");
    const myPara1 = document.createElement("p");
    const myPara2 = document.createElement("p");
    const myPara3 = document.createElement("p");
    const myList = document.createElement("ul");

    myH2.textContent = hero.name;
    myPara1.textContent = `Secret identity: ${hero.secretIdentity}`;
    myPara2.textContent = `Age: ${hero.age}`;
    myPara3.textContent = "Superpowers:";

    const superPowers = hero.powers;
    for (const power of superPowers) {
      const listItem = document.createElement("li");
      listItem.textContent = power;
      myList.appendChild(listItem);
    }

    myArticle.appendChild(myH2);
    myArticle.appendChild(myPara1);
    myArticle.appendChild(myPara2);
    myArticle.appendChild(myPara3);
    myArticle.appendChild(myList);

    section.appendChild(myArticle);
  }
}

بدأنا بتخزين قيمة الخاصية members لكائن جافا سكريبت في متغير جديد. وهذه الخاصية هي مصفوفة تضم عدة كائنات تضم معلومات عن كل بطل. ثم تنقلنا بين كائنات الخاصية باستخدام حلقة for...of لـِ:

  1. إنشاء عدة عناصر HTML جديدة وهي: <article> و <h2> وثلاث فقرات نصية <p> و <ul>.
  2. ضبط محتوى <h2> ليضم اسم البطل name.
  3. ملئ الفقرات النصية الثلاث بقيم الخاصيتين secretIdentity و age وبعبارة "Superpowers" لتقديم المعلومات الموجودة في القائمة.
  4. تخزين قيمة الخاصية powers في متغير آخر جديد يُدعى superPowers وتضم الخاصية مصفوفة تضم القوى الخارقة التي يتمتع بها البطل.
  5. استخدام حلقة for...of من جديد للتنقل بين القوى التي يمتلكها البطل وإنشاء عنصر <li> لوضع القوة ضمنه ثم نلحق عنصر القائمة listItem بالقائمة غير المرتبة <ul> (التس تُسمى <myList).
  6. إلحاق العنصر <h2> والفقرات النصية الثلاث <p> والقائمة <ul> بالعنصر <article> (الذي يُسمى myArticle) وإلحاقه بالعنصر <section>. وانتبه إلى إلحاق العناصر وفق الترتيب السابق تمامًا، فسيعكس ذلك ترتيب الملعومات التي ستُعرض في صفحة HTML.

ملاحظة: إن واجهت صعوبة في تنفيذ التمرين، عُد إلى الشيفرة المصدرية له أو اطلع على النسخة الجاهزة منه.

ملاحظة: إن واجهت صعوبة في استيعاب استخدام ترميز (النقطة والأقواس المربعة) في الوصول إلى كائنات جافا سكريبت، سيساعدك فتح الملف superheroes.json في نافذة أخرى لمحررك النصي والرجوع إليه عند متابعة شيفرة جافا سكريبت. كما يمكنك العودة إلى مقال أساسيات العمل مع الكائنات في جافا سكريبت لمعلومات أوضح عن طريقة الترميز هذه.

استدعاء توابع المستوى اﻷعلى

علينا أخيرًا استدعاء الدالة الأعلى مستوى ()populate

populate();

التحويل بين الكائنات والنصوص

يبدو التمرين السابق بسيطًا من ناحية الوصول إلى كائنات جافا سكريبت، لأننا حولنا الاستجابة التي أرسلها الخادم مباشرة إلى كائن جافا سكريبت باستخدام response.json.

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

  • ()parse: يقبل نص JSON كمعامل ويعيد كائن جافا سكريبت الموافق.
  • ()stringify: يقبل كائنًا كمعامل له، ويعيد نص JSON الموافق.

بإمكانك رؤية عمل التابع الأول في النسخة الجاهزة من التمرين السابق (انظر أيضًا إلى شيفرته المصدرية) وهو يفعل تمامًا ما تفعله النسخة التي بنيناها باستثناء أننا:

  • حصلنا على الاستجابة على شكل سلسلة نصية بدلًا من تنسيق JSON لاستخدامنا التابع ()text للحصول على الاستجابة.
  • استخدمنا التابع ()parse لتحويل النص إلى كائن جافا سكريبت.

إليك مقطع الشيفرة الموافق لما ذكرنا:

async function populate() {
  const requestURL =
    "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json";
  const request = new Request(requestURL);

  const response = await fetch(request);
  const superHeroesText = await response.text();

  const superHeroes = JSON.parse(superHeroesText);
  populateHeader(superHeroes);
  populateHeroes(superHeroes);
}

وكما ترى، يعمل التابع ()stringify بطريقة معكوسة. جرّب اﻵن إدخال اﻷسطر التالية إلى طرفية جافا سكريبت في متصفحك سطرًا تلو اﻵخر:

let myObj = { name: "Chris", age: 38 };
myObj;
let myString = JSON.stringify(myObj);
myString;

ننشئ هنا كائن جافا سكريبت ثم نتحقق من محتواه ونحوّله بعدها إلى نص JSON باستخدام التابع ()stringify. نخزّن القيمة المعادة في متغيّر جيد ثم نتحقق منه مجددًا.

الخلاصة

قدمنا في هذا المقال دليلًا بسيطًا لاستخدام تنسيق JSON في برامجك بما في ذلك إنشاء وتفسير نصوص JSON وكيفية الوصول إلى البيانات التي يضمها.

ترجمة -وبتصرف- لمقال Working with JSON

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...