تخطَّ إلى المحتوى

JSON في JavaScript: JSON.stringify و JSON.parse

الدرس 19 من 28 · JavaScript

عندما يطلب تطبيق الطقس درجة الحرارة من الخادم، بأي لغة يتفاهمان؟ التطبيق قد يكون مكتوباً بـ JavaScript، والخادم بـ Python أو PHP. يحتاجان إلى صيغة مشتركة يفهمها الجميع. هذه الصيغة هي JSON. ستستخدمها مع كل خادم، وفي حفظ البيانات، وفي ملفات الإعدادات. في هذا الدرس ستتعلم قراءتها وكتابتها.

JSON اختصار لـ JavaScript Object Notation، أي «طريقة كتابة كائنات JavaScript». هي نص يصف بيانات بشكل يشبه الكائنات التي تعرفها:

{
"name": "سارة",
"age": 14,
"isStudent": true,
"hobbies": ["القراءة", "الرسم"],
"address": { "city": "طنطا" },
"phone": null
}

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

JSON تشبه كائنات JavaScript، لكنها أكثر صرامة:

القاعدة صحيح خطأ
أسماء الخصائص بين علامتي تنصيص مزدوجتين "name": "سارة" name: "سارة"
النصوص بعلامات مزدوجة فقط "طنطا" 'طنطا'
لا فاصلة بعد آخر عنصر [1, 2] [1, 2,]
لا تعليقات // تعليق
لا دوال ولا undefined "f": function() {}

والأنواع المسموحة ستة فقط: نص، ورقم، وقيمة منطقية، و null، ومصفوفة، وكائن.

الكائن يعيش في ذاكرة البرنامج، ولا يمكن إرساله عبر الإنترنت أو حفظه كما هو. نحوّله أولاً إلى نص:

const user = { name: "سارة", age: 14, hobbies: ["القراءة", "الرسم"] };
const text = JSON.stringify(user);
console.log(text);
console.log(typeof text);
الناتج
{"name":"سارة","age":14,"hobbies":["القراءة","الرسم"]}
string

النتيجة نص من نوع string، مع أنها تشبه الكائن. لم يعد بإمكانك كتابة text.name.

وللحصول على نص منسق سهل القراءة، أضف معاملين: null ثم عدد مسافات الإزاحة:

console.log(JSON.stringify({ name: "سارة", age: 14 }, null, 2));
الناتج
{
"name": "سارة",
"age": 14
}
const item = {
title: "كتاب",
price: undefined,
show() {
return this.title;
},
};
console.log(JSON.stringify(item));
الناتج
{"title":"كتاب"}

الخصائص التي قيمتها undefined والدوال تُحذف بصمت، لأن JSON للبيانات فقط. وكائنات التاريخ Date تتحول إلى نصوص.

العملية العكسية: تستقبل نصاً من الخادم وتحوّله إلى كائن تتعامل معه:

const received = '{"city":"القاهرة","temp":31,"rainy":false}';
const weather = JSON.parse(received);
console.log(weather.city);
console.log(weather.temp + 1);
console.log(typeof weather);
الناتج
القاهرة
32
object

بعد parse أصبح عندك كائن حقيقي: تقرأ خصائصه بالنقطة، وأرقامه أرقام حقيقية تُجمع وتُطرح.

JSON.stringify JSON.parse
تأخذ كائناً أو مصفوفة نصاً
تُرجع نصاً كائناً أو مصفوفة
متى قبل الإرسال أو الحفظ بعد الاستقبال أو القراءة

النص غير الصالح يسبب خطأ

Section titled “النص غير الصالح يسبب خطأ”

إذا كان النص لا يتبع قواعد JSON، ترمي JSON.parse خطأ يوقف البرنامج:

try {
JSON.parse("{ name: 'سارة' }");
} catch (error) {
console.log("نص غير صالح:", error.name);
}
الناتج
نص غير صالح: SyntaxError

هذا النص يبدو طبيعياً ككائن JavaScript، لكنه ليس JSON صالحاً: اسم الخاصية بلا علامات تنصيص، والنص بعلامات مفردة.

أغلب ما يرجعه الخادم مصفوفة كائنات. بعد parse تستخدم معها كل دوال المصفوفات التي تعلمتها:

const response = '[{"title":"قلم","price":5},{"title":"حقيبة","price":250}]';
const items = JSON.parse(response);
console.log(items.length);
console.log(items.map((item) => item.title));
console.log(items.filter((item) => item.price > 100));
الناتج
2
[ 'قلم', 'حقيبة' ]
[ { title: 'حقيبة', price: 250 } ]

عرفت في الدرس السابق أن النشر ... ينسخ المستوى الأول فقط. للنسخ العميق لكائن فيه كائنات داخلية، توجد دالة مدمجة:

const original = { name: "سارة", address: { city: "طنطا" } };
const deep = structuredClone(original);
deep.address.city = "أسوان";
console.log(original.address.city);
console.log(deep.address.city);
الناتج
طنطا
أسوان

وستجد في أكواد قديمة الحيلة JSON.parse(JSON.stringify(obj)). تؤدي نفس الغرض تقريباً، لكنها تفقد التواريخ والدوال و undefined. استخدم structuredClone.

جرّب بنفسكJavaScript
أو اضغط Ctrl + Enter

الناتج

أضف خاصية birthday قيمتها undefined إلى الكائن، وشاهد هل تظهر في النص. ثم غيّر الاستدعاء إلى JSON.stringify(student, null, 2).

  • محاولة قراءة خاصية من نص JSON: text.name تُرجع undefined، لأن text نص وليس كائناً. استخدم JSON.parse أولاً.
  • استخدام parse مع كائن: JSON.parse(user) خطأ، لأن parse تنتظر نصاً.
  • كتابة JSON بعلامات تنصيص مفردة أو فاصلة أخيرة: يرفضها parse. JSON أكثر صرامة من JavaScript.

سؤال

ما نوع القيمة التي تُرجعها JSON.stringify؟

سؤال

أي نص مما يلي JSON صالح؟

  • JSON صيغة نصية مشتركة لتبادل البيانات بين كل اللغات.
  • قواعدها صارمة: علامات تنصيص مزدوجة، ولا فاصلة أخيرة، ولا تعليقات ولا دوال.
  • JSON.stringify تحوّل الكائن إلى نص، و JSON.parse تعيد النص كائناً.
  • النص غير الصالح يسبب SyntaxError، فاستخدم try و catch.
  • للنسخ العميق استخدم structuredClone.