شرح JSON في JavaScript: كيفية تحليل البيانات واستخدام JSON.stringify() باحتراف
تُعد JSON، أو JavaScript Object Notation، من أكثر صيغ تبادل البيانات انتشاراً في تطبيقات الويب الحديثة. فعند استخدام أي تطبيق ويب تقريباً، هناك احتمال كبير أن البيانات التي تنتقل بين الخادم والمتصفح تكون بصيغة JSON. وتكمن أهميتها في أنها خفيفة، سهلة القراءة، ومدعومة على نطاق واسع في مختلف اللغات والمنصات.
في هذا الدليل، سنوضح الفرق بين JSON وJavaScript، ثم نستعرض كيفية تحليل بيانات JSON داخل المتصفح، وكيفية التعامل معها في مشاريع Node.js، بالإضافة إلى شرح استخدام JSON.parse() وJSON.stringify() بأسلوب عملي وواضح.
ما الفرق بين JSON وJavaScript؟
رغم أن صيغة JSON تبدو شبيهة جداً بكائنات JavaScript، فإنها ليست هي نفسها. من الأفضل النظر إلى JSON باعتبارها صيغة بيانات وليست كوداً تنفيذياً. هي تشبه ملفاً نصياً منظماً، صُمم ليكون بسيطاً ومناسباً لنقل البيانات وتخزينها.
سبب التشابه هو أن JSON مستوحاة من بناء JavaScript، لكن هناك قواعد أكثر صرامة يجب الالتزام بها.
الفرق بين كائنات JSON وكائنات JavaScript
إليك مثالاً على كائن بصيغة JSON:
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
الفرق الأهم هنا هو أن جميع المفاتيح والقيم النصية في JSON يجب أن تكون محاطة بعلامات اقتباس مزدوجة ".
أما في كائنات JavaScript العادية، أو ما يُعرف باسم Object Literals، فهناك مرونة أكبر:
const profile = {
name: 'Jane Doe',
'favorite-game': 'Stardew Valley',
subscriber: false
};
لاحظ أن المفتاح favorite-game كُتب بين علامات اقتباس لأنه يحتوي على الشرطة -. وإذا أردت تجنب ذلك، يمكنك استخدام camelCase مثل favoriteGame أو الشرطة السفلية مثل favorite_game.
الفرق بين مصفوفات JSON ومصفوفات JavaScript
مصفوفات JSON تعمل بطريقة قريبة جداً من المصفوفات في JavaScript، ويمكن أن تحتوي على نصوص وأرقام وقيم منطقية وكائنات أخرى.
[
{
"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 عند وصولها من ملف أو من واجهة برمجة تطبيقات API تكون عادة على شكل نص، وليس كائناً قابلاً للاستخدام المباشر داخل البرنامج. لذلك نحتاج إلى تحويلها إلى بنية مفهومة من قبل JavaScript باستخدام JSON.parse()، أو تحويل الكائنات إلى نص بصيغة JSON باستخدام JSON.stringify().
على سبيل المثال، قد تستقبل من واجهة API استجابة بالشكل التالي:
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
هذا يبدو ككائن برمجي، لكنه في الأصل نص منظم. وللاستفادة منه داخل التطبيق، يجب تحليله أولاً.
كيفية تحليل JSON داخل المتصفح
في بيئة المتصفح، غالباً ما تتعامل مع JSON عند جلب البيانات من واجهة API أو إرسالها إليها.
استخدام fetch() لتحليل JSON
الطريقة الأسهل لجلب بيانات من واجهة API هي استخدام fetch(). وتوفّر هذه الدالة التابع .json() الذي يحول الاستجابة تلقائياً إلى كائن أو مصفوفة قابلة للاستخدام.
fetch('https://api.chucknorris.io/jokes/random?category=dev')
.then(res => res.json())
.then(data => console.log(data));
الدالة res.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، فإنه بعد التحليل يصبح كائناً عادياً من نوع JavaScript يمكن التعامل معه مباشرة.
استخدام JSON.stringify() لإرسال البيانات إلى API
إذا أردت إرسال بيانات إلى واجهة 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));
الناتج سيكون نصاً من نوع 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);
});
بهذه الطريقة تكون قد:
- استقبلت بيانات
JSONمن خلالfetch(). - حللتها باستخدام
.json(). - ثم حولت كائناً برمجياً إلى نص
JSONبواسطةJSON.stringify()قبل الإرسال.
هل يمكن تحميل ملف JSON محلي داخل المتصفح؟
عملياً، لا يُنصح بذلك، وغالباً لن يسمح المتصفح بتحميل ملف محلي مباشرة باستخدام 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."
}
]
ثم حاولت قراءته داخل صفحة HTML مباشرة، فستظهر لك رسالة تفيد بأن مخطط file غير مدعوم.
Fetch API cannot load file://<path>/jokes.json. URL scheme "file" is not supported
هذا السلوك طبيعي ومفيد من ناحية الحماية. والحل الأفضل داخل المتصفح هو تحويل البيانات إلى ملف 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."
}
];
ثم تضمين الملف داخل الصفحة:
<script src="jokes.js"></script>
<script>
console.log(jokes);
</script>
بهذه الطريقة يمكنك استخدام المصفوفة jokes بحرية داخل مشروعك.
كيفية تحليل JSON في Node.js
تسمح بيئة Node.js بتشغيل JavaScript خارج المتصفح، وهي مناسبة جداً للتعامل مع الملفات المحلية وواجهات API. لذلك من المهم معرفة الطرق الصحيحة لتحليل ملفات JSON فيها.
استخدام require() لقراءة ملف JSON
إذا كان لديك ملف JSON محلي، فأسهل حل هو تحميله عبر require() كما لو كان وحدة عادية:
const jokes = require('./jokes.json');
سيتم تحليل الملف تلقائياً، ويمكنك الوصول إلى البيانات مباشرة:
const jokes = require('./jokes.json');
console.log(jokes[0].value);
لكن انتبه إلى نقطتين مهمتين:
- الطريقة
synchronous، أي إنها توقف تنفيذ البرنامج حتى ينتهي التحميل. - مناسبة أكثر للملفات الثابتة، لأن التغييرات على الملف أثناء التشغيل لن تظهر إلا بعد إعادة تشغيل البرنامج.
استخدام fs.readFileSync() مع JSON.parse()
هذه طريقة شائعة وأكثر وضوحاً عند الحاجة إلى التحكم في القراءة والتحليل بشكل منفصل.
ابدأ بإضافة وحدة fs:
const fs = require('fs');
ثم اقرأ الملف:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
تحديد الترميز utf8 مهم جداً، لأن عدم تحديده سيجعل الناتج من نوع Buffer بدلاً من نص مقروء.
بعد القراءة، استخدم JSON.parse() لتحويل النص إلى كائن أو مصفوفة:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
const jokes = JSON.parse(jokesFile);
console.log(jokes[0].value);
تتميز هذه الطريقة بأنها مباشرة وسهلة الفهم، لكنها أيضاً synchronous، لذلك قد لا تكون مثالية مع الملفات الكبيرة.
تبسيط القراءة عبر دالة مساعدة
إذا كنت ستقرأ الملف أكثر من مرة، فمن الأفضل إنشاء دالة مخصصة:
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!');
في هذا المثال، ستتم طباعة السطر الأخير أولاً لأن القراءة تحدث في الخلفية. وهذه الطريقة أفضل عند التعامل مع ملفات كبيرة نسبياً أو عند الرغبة في إبقاء التطبيق مستجيباً.
متى تستخدم JSON.parse() ومتى تستخدم JSON.stringify()؟
| الحالة | الدالة المناسبة | النتيجة |
|---|---|---|
استقبال نص بصيغة JSON |
JSON.parse() |
تحويل النص إلى كائن أو مصفوفة |
إرسال كائن أو مصفوفة إلى API |
JSON.stringify() |
تحويل البيانات إلى نص JSON |
قراءة ملف JSON في Node.js |
JSON.parse() بعد القراءة |
استخدام البيانات داخل التطبيق |
| تخزين بيانات بصيغة نصية | JSON.stringify() |
إخراج منسق قابل للنقل والتخزين |
أفضل الممارسات عند التعامل مع JSON
- احرص على التمييز بين النص الخام وكائن
JavaScriptبعد التحليل. - استخدم
try...catchعند تطبيقJSON.parse()على بيانات غير مضمونة. - لا تعتمد على تحميل الملفات المحلية داخل المتصفح مباشرة.
- في
Node.js، فضّل الطرق غير المتزامنة عند التعامل مع ملفات كبيرة. - استخدم
JSON.stringify()قبل الإرسال إلى الواجهات البرمجية أو التخزين النصي.
الخلاصة التقنية
فهم JSON ليس مجرد مهارة أساسية في JavaScript، بل هو جزء محوري من بناء التطبيقات الحديثة. عملياً، يمكن تلخيص الفكرة في معادلة بسيطة: عندما تستقبل نصاً منظماً استخدم JSON.parse()، وعندما تريد إرسال البيانات أو حفظها كنص استخدم JSON.stringify(). أما اختيار طريقة القراءة في Node.js، فيعتمد على حجم الملف وطبيعة التطبيق وما إذا كنت تحتاج إلى أداء متزامن أو غير متزامن. وكلما أتقنت هذا الفرق، أصبح تعاملك مع API والملفات المحلية أكثر كفاءة واحترافية.