شرح JSON في JavaScript: كيفية تحليل الكائنات وتحويلها باستخدام JSON.parse() وJSON.stringify()
مقدمة: لماذا تُعد JSON أساسية في تطوير الويب؟
تُعد JSON، أو JavaScript Object Notation، من أكثر صيغ تبادل البيانات استخداماً في تطبيقات الويب الحديثة. فعند التواصل بين الواجهة الأمامية والخادم، أو عند استدعاء واجهات API، غالباً ما تكون البيانات المرسلة والمستقبلة مكتوبة بهذه الصيغة.
ورغم أن شكل JSON يبدو قريباً جداً من كائنات JavaScript، فإن بينهما فروقاً مهمة يجب فهمها جيداً. في هذا الدليل سنستعرض هذه الفروق، ثم نوضح كيفية استخدام JSON.parse() وJSON.stringify() والتعامل مع ملفات JSON داخل المتصفح وبيئة Node.js.

الفرق بين JSON وJavaScript
من الأخطاء الشائعة الاعتقاد بأن JSON مجرد كائن JavaScript عادي، لكن الحقيقة أنها صيغة نصية لتخزين البيانات وتمثيلها ونقلها. بمعنى آخر، JSON ليست نوعاً تنفيذياً بحد ذاتها، بل نص منظم وفق قواعد محددة.
هذا التشابه الكبير في البنية جاء لأن صيغة JSON مستوحاة من أسلوب كتابة الكائنات في JavaScript، لكنه لا يعني أنهما الشيء نفسه.
الفرق بين كائن JSON وObject Literal في JavaScript
إليك مثالاً على كائن بصيغة JSON:
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
الفرق الأهم هنا أن جميع المفاتيح والقيم النصية في JSON يجب أن تُكتب بين علامتي اقتباس مزدوجتين "".
أما في كائنات JavaScript العادية، فهناك مرونة أكبر:
const profile = {
name: 'Jane Doe',
'favorite-game': 'Stardew Valley',
subscriber: false
};
في المثال السابق:
- المفتاح
nameلم يحتج إلى علامات اقتباس. - القيم النصية كُتبت باستخدام اقتباس مفرد
' '. - المفتاح
favorite-gameاحتاج إلى اقتباس لأنه يحتوي على شرطة-.
إذا أردت تجنب الاقتباس في أسماء الخصائص داخل JavaScript، يمكنك استخدام أساليب تسمية مثل camelCase أو snake_case، مثل favoriteGame أو favorite_game.
الفرق بين مصفوفات JSON ومصفوفات JavaScript
تعمل مصفوفات JSON تقريباً بالطريقة نفسها التي تعمل بها المصفوفات في JavaScript. يمكن أن تحتوي على:
- نصوص
- أرقام
- قيم منطقية مثل
trueوfalse - كائنات أخرى
- مصفوفات متداخلة
مثال على مصفوفة JSON:
[
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
},
{
"name": "John Doe",
"favorite-game": "Dragon Quest XI",
"subscriber": true
}
]
والصيغة المقابلة لها في JavaScript تكون كالتالي:
const profiles = [
{
name: 'Jane Doe',
'favorite-game': 'Stardew Valley',
subscriber: false
},
{
name: 'John Doe',
'favorite-game': 'Dragon Quest XI',
subscriber: true
}
];
هل JSON كائن أم نص؟
رغم أن JSON قد يبدو ككائن جاهز للاستخدام، فإنه في الواقع نص string. وهذا هو السبب الذي يجعلك بحاجة إلى تحليله قبل التعامل معه برمجياً.
على سبيل المثال، إذا كان لديك ملف باسم jane-profile.json أو profiles.json، فإن محتوى الملف يكون نصاً منسقاً وفق قواعد JSON. وكذلك عند استدعاء واجهة API، فإن الاستجابة غالباً تصل على شكل نص بصيغة JSON.
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
ولكي تستخدم هذه البيانات داخل برنامجك، يجب تحويلها إلى بنية يفهمها المحرك البرمجي، مثل كائن أو مصفوفة في JavaScript. وهنا يأتي دور JSON.parse().
كيفية تحليل JSON في المتصفح
في بيئة المتصفح، غالباً ما تتعامل مع JSON عند جلب البيانات من خدمة خارجية أو إرسال بيانات إلى خادم عبر API.
استخدام fetch لتحليل البيانات
تُعد الدالة fetch من أبسط الطرق لجلب البيانات من واجهات API. وعند استلام الاستجابة، يمكنك استخدام الدالة .json() لتحويلها مباشرة إلى كائن أو مصفوفة قابلة للاستخدام داخل JavaScript.
fetch('https://api.chucknorris.io/jokes/random?category=dev')
.then(res => res.json())
.then(data => console.log(data));
الدالة .json() تتكفل بتحويل الاستجابة من صيغة JSON إلى كائن JavaScript يمكنك التعامل معه مباشرة.
مثال على ناتج محتمل:
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
}
رغم أن الناتج يبدو شبيهاً بـ JSON، فإنه بعد تنفيذ .json() يصبح كائناً فعلياً من نوع JavaScript object.
استخدام JSON.stringify() قبل إرسال البيانات
إذا أردت إرسال بيانات إلى واجهة API، فعادة تبدأ بإنشاء كائن عادي داخل JavaScript، ثم تحوله إلى نص بصيغة JSON باستخدام JSON.stringify().
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
console.log(JSON.stringify(newJoke));
console.log(typeof JSON.stringify(newJoke));
الناتج سيكون نصاً:
{"categories":["dev"],"value":"Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."}
ونوعه سيكون string.
ويمكن بعد ذلك إرساله في طلب POST بالشكل التالي:
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
fetch('https://api.chucknorris.io/jokes/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newJoke),
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => {
console.error(err);
});
في هذا السيناريو:
- أنشأت كائناً عادياً داخل
JavaScript. - حوّلته إلى نص بصيغة
JSONعبرJSON.stringify(). - أرسلته إلى الخادم ضمن جسم الطلب
body.
هل يمكن تحميل ملف JSON محلياً داخل المتصفح؟
من الناحية العملية، لا يُنصح بتحميل ملف JSON محلي مباشرة من المسار file:// داخل المتصفح باستخدام fetch. فالمتصفحات تمنع ذلك لأسباب أمنية مرتبطة بسياسات الوصول المحلية.
إذا كان لديك ملف jokes.json مثلاً:
[
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
},
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "ae-78cogr-cb6x9hluwqtw",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/ae-78cogr-cb6x9hluwqtw",
"value": "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris."
}
]
ثم حاولت جلبه داخل صفحة محلية، فستظهر رسالة خطأ مشابهة لما يلي:
Fetch API cannot load file://<path>/jokes.json. URL scheme "file" is not supported
الحل العملي داخل المتصفح
إذا كانت البيانات محلية وتريد استخدامها في مشروع بسيط، فيمكنك تحويل محتوى JSON إلى ملف JavaScript عادي وتعريفه في متغير:
const jokes = [
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
},
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "ae-78cogr-cb6x9hluwqtw",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/ae-78cogr-cb6x9hluwqtw",
"value": "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris."
}
];
بعدها يمكنك تضمين الملف ضمن الصفحة واستخدام المتغير مباشرة في سكربتاتك.
هذه الطريقة مفيدة في المشاريع الصغيرة أو عند بناء نماذج تجريبية، لكنها ليست بديلاً عن العمل عبر خادم محلي أو بيئة تطوير مناسبة.
كيفية تحليل JSON في Node.js
عند العمل في Node.js، يصبح التعامل مع ملفات JSON أكثر مرونة، لأنك تعمل خارج قيود المتصفح، ويمكنك قراءة الملفات المحلية مباشرة من نظام الملفات.
الطريقة الأسرع: استخدام require()
إذا كان لديك ملف JSON محلي، يمكنك تحميله باستخدام require() تماماً كما تفعل مع الوحدات البرمجية:
const jokes = require('./jokes.json');
بعد ذلك يصبح الملف محللاً تلقائياً، ويمكن استخدامه مباشرة:
const jokes = require('./jokes.json');
console.log(jokes[0].value);
لكن انتبه إلى نقطتين مهمتين:
require()يعمل بشكل متزامنsynchronous.- يحمّل البيانات في الذاكرة مرة واحدة، لذلك إن تغيّر الملف أثناء تشغيل البرنامج فلن ترى التحديثات إلا بعد إعادة التشغيل.
لهذا تُعد هذه الطريقة مناسبة أكثر للملفات الثابتة أو إعدادات المشروع.
استخدام fs.readFileSync() مع JSON.parse()
إذا أردت تحكماً أكبر، فاستخدم وحدة fs لقراءة الملف، ثم حوّل النص الناتج إلى كائن أو مصفوفة عبر JSON.parse().
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
const jokes = JSON.parse(jokesFile);
console.log(jokes[0].value);
الخطوات هنا واضحة:
- قراءة الملف باستخدام
fs.readFileSync(). - تحديد الترميز
utf8حتى يتم إرجاع النص بشكل صحيح. - تحويل النص الناتج باستخدام
JSON.parse().
إذا لم تُحدد الترميز، فقد تستلم البيانات على شكل Buffer بدلاً من نص مباشر.
إنشاء دالة مساعدة لإعادة قراءة الملف
في حال كان الملف قد يتغير أثناء تشغيل التطبيق، يمكنك إنشاء دالة صغيرة لإعادة القراءة كلما احتجت إلى أحدث نسخة من البيانات:
const fs = require('fs');
const readFile = path => fs.readFileSync(path, 'utf8');
const jokesFile1 = readFile('./jokes.json');
const jokes1 = JSON.parse(jokesFile1);
console.log(jokes1[0].value);
const jokesFile2 = readFile('./jokes.json');
const jokes2 = JSON.parse(jokesFile2);
console.log(jokes2[0].value);
هذه المقاربة عملية عندما تكون البيانات قابلة للتحديث وتحتاج إلى إعادة تحميلها عند الطلب.
استخدام fs.readFile() مع JSON.parse()
إذا كنت تتعامل مع ملفات كبيرة نسبياً، أو لا تريد أن يتوقف تنفيذ بقية البرنامج أثناء القراءة، فاستخدم fs.readFile() لأنه غير متزامن asynchronous.
const fs = require('fs');
fs.readFile('./jokes.json', 'utf8', (err, data) => {
if (err) console.error(err);
const jokes = JSON.parse(data);
console.log(jokes[0].value);
});
console.log('This will run first!');
الميزة هنا أن السطر الأخير يُنفذ أولاً، بينما تُقرأ البيانات في الخلفية. وهذا مناسب لتحسين الأداء في التطبيقات التي لا ينبغي أن تتوقف أثناء عمليات القراءة.
ومع ذلك، تذكّر أن fs.readFile() في النهاية يحمّل الملف كاملاً إلى الذاكرة. إذا كنت تتعامل مع ملفات ضخمة جداً، فقد تكون streams خياراً أفضل.
استخدام JSON.stringify() في Node.js
كما هو الحال في المتصفح، يمكنك داخل Node.js تحويل الكائنات والمصفوفات إلى نص بصيغة JSON باستخدام JSON.stringify().
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
console.log(JSON.stringify(newJoke));
يفيد ذلك كثيراً عند:
- إرجاع استجابة
API. - حفظ البيانات في ملف.
- إرسال البيانات إلى خدمة خارجية.
- تسجيل الكائنات بصيغة نصية منظمة.
متى تستخدم JSON.parse() ومتى تستخدم JSON.stringify()؟
| الحالة | الدالة المناسبة | النتيجة |
|---|---|---|
لديك نص بصيغة JSON وتريد استخدامه داخل JavaScript |
JSON.parse() |
تحويل النص إلى كائن أو مصفوفة |
لديك كائن أو مصفوفة داخل JavaScript وتريد إرسالها أو تخزينها |
JSON.stringify() |
تحويل الكائن إلى نص بصيغة JSON |
أفضل الممارسات عند التعامل مع JSON
- تأكد دائماً من صحة بنية النص قبل تمريره إلى
JSON.parse(). - استخدم
try...catchعند تحليل بيانات غير موثوقة لتجنب توقف التطبيق عند وجود خطأ في الصيغة. - لا تعتمد على
require()مع ملفاتJSONالمتغيرة باستمرار إذا كنت تحتاج إلى أحدث التحديثات فوراً. - استخدم
utf8عند قراءة الملفات النصية عبرfs. - إذا كان الملف كبيراً جداً، ففكر في استخدام تدفقات القراءة
streamsبدلاً من تحميل الملف كاملاً في الذاكرة.
الخلاصة التقنية
فهم الفرق بين JSON كصيغة نصية وبين كائنات JavaScript خطوة أساسية لأي مطور ويب. عملياً، ستستخدم JSON.parse() عند استقبال البيانات، وJSON.stringify() عند إرسالها أو تخزينها. في المتصفح، تبقى fetch الخيار الأسهل للتعامل مع واجهات API، بينما يوفر Node.js أكثر من أسلوب لقراءة ملفات JSON بحسب حجم الملف وطبيعة المشروع. الاختيار الذكي بين الطرق المتزامنة وغير المتزامنة لا يحسن الأداء فقط، بل يجعل تطبيقك أكثر استقراراً وقابلية للتوسع.