شرح JSON في JavaScript: كيفية تحليل البيانات وتحويلها باستخدام JSON.parse() وJSON.stringify()
أصبح تنسيق JSON جزءاً أساسياً من تطوير الويب الحديث، فهو الصيغة الأشهر لتبادل البيانات بين الواجهات الأمامية والخوادم وواجهات API. وإذا سبق لك التعامل مع تطبيق ويب أو خدمة خارجية، فغالباً أنك استخدمت JSON بشكل مباشر أو غير مباشر.
في هذا الدليل، سنتعرف على الفرق بين JSON وJavaScript، ثم نشرح كيفية تحليل البيانات باستخدام JSON.parse() وتحويل الكائنات إلى نصوص باستخدام JSON.stringify()، سواء داخل المتصفح أو في مشاريع Node.js.
ما هو JSON ولماذا يُستخدم بكثرة؟
JSON هو اختصار لعبارة JavaScript Object Notation، وهو تنسيق نصي خفيف لتخزين البيانات ونقلها. ورغم أن شكله قريب جداً من كائنات JavaScript، فإنه ليس كوداً تنفيذياً بحد ذاته، بل مجرد نص منظّم وفق قواعد محددة.
تكمن قوة JSON في أنه:
- سهل القراءة للبشر.
- سهل التحليل للبرامج.
- مدعوم في معظم لغات البرمجة.
- مثالي لعمليات التواصل مع
APIوتخزين الإعدادات والبيانات.
الفرق بين JSON وJavaScript
رغم التشابه الكبير في الشكل، هناك فروق مهمة يجب فهمها لتجنب الأخطاء أثناء التطوير.
كائن JSON مقابل الكائن العادي في JavaScript
فيما يلي مثال على كائن JSON صحيح:
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
الفرق الأساسي هنا أن جميع المفاتيح والقيم النصية داخل JSON يجب أن تُكتب بين علامتي اقتباس مزدوجتين ".
أما في JavaScript، فيمكن كتابة الكائن بصيغة أكثر مرونة:
const profile = {
name: 'Jane Doe',
'favorite-game': 'Stardew Valley',
subscriber: false
};
في هذا المثال، المفتاح favorite-game احتاج إلى علامات اقتباس لأنه يحتوي على الشرطة -. وإذا أردت تجنب ذلك، يمكنك استخدام صيغة مثل favoriteGame أو favorite_game.
مصفوفات JSON ومصفوفات JavaScript
المصفوفات في JSON تشبه إلى حد كبير المصفوفات في JavaScript، ويمكن أن تحتوي على:
- نصوص.
- أرقام.
- قيم منطقية مثل
trueوfalse. - كائنات
JSONأخرى.
مثال على مصفوفة 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. فعندما تحصل على استجابة من API أو تقرأ ملفاً بامتداد .json، فأنت تتعامل مع بيانات نصية وليست كائناً قابلاً للاستخدام المباشر في البرنامج.
على سبيل المثال، قد تصلك البيانات بهذا الشكل:
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
حتى تتمكن من استخدامها داخل التطبيق، يجب تحويل هذا النص إلى كائن أو مصفوفة مفهومة في JavaScript. هنا يأتي دور JSON.parse().
كيفية تحليل JSON داخل المتصفح
في بيئة المتصفح، غالباً ما تتعامل مع JSON عبر استدعاءات API. وأكثر وسيلة شائعة لذلك هي fetch().
استخدام fetch() لتحليل JSON
توفر الدالة fetch() طريقة سهلة لجلب البيانات، كما أن الكائن الناتج يحتوي على الدالة .json() التي تقوم بتحويل الاستجابة إلى كائن JavaScript قابل للاستخدام.
fetch('https://api.chucknorris.io/jokes/random?category=dev')
.then(res => res.json())
// تقوم .json() بتحويل استجابة JSON إلى كائن JavaScript
.then(data => console.log(data));
النتيجة التي ستظهر في وحدة التحكم قد تبدو كأنها 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.stringify() قبل إرسال البيانات
إذا أردت إرسال بيانات إلى API عبر طلب POST، فلن يكون من الكافي إرسال كائن 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));
// {"categories":["dev"],"value":"Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."}
console.log(typeof JSON.stringify(newJoke));
// string
هذه الدالة لا تعمل مع الكائنات فقط، بل تدعم أيضاً المصفوفات وغيرها من البنى القابلة للتحويل.
وإذا كنت سترسل البيانات إلى واجهة برمجية، فقد يبدو الكود بهذا الشكل:
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 صالح للإرسال عبر الشبكة.
هل يمكن قراءة ملف JSON محلياً داخل المتصفح؟
من الناحية العملية، لا يُنصح بتحميل ملفات JSON المحلية مباشرة عبر المتصفح باستخدام fetch() من مسار file://، لأن المتصفحات تمنع ذلك لأسباب أمنية.
لنفترض أن لديك ملف 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."
}
]
وإذا حاولت قراءته بهذه الطريقة:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>Fetch Local JSON</title>
</head>
<script>
fetch('./jokes.json', { mode: 'no-cors' })
.then((res) => res.json())
.then((data) => console.log(data));
</script>
</html>
فستظهر رسالة خطأ مشابهة لما يلي:
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."
}
];
ثم تضمينه في الصفحة:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>Fetch Local JSON</title>
</head>
<script src="jokes.js"></script>
<script>
console.log(jokes);
</script>
</html>
بعد ذلك يمكنك استخدام المصفوفة jokes بحرية داخل التطبيق. كما يمكن استخدام JavaScript modules لهذا الغرض في المشاريع الحديثة.
كيفية تحليل JSON في Node.js
في بيئة Node.js، يصبح التعامل مع ملفات JSON المحلية أكثر سهولة، لأنك تعمل مباشرة مع نظام الملفات.
سنفترض في الأمثلة التالية وجود ملف باسم jokes.json يحتوي على البيانات نفسها المذكورة سابقاً.
قراءة ملف JSON باستخدام require()
هذه أبسط طريقة عندما يكون الملف محلياً وثابتاً نسبياً:
const jokes = require('./jokes.json');
سيقوم Node.js بتحليل الملف تلقائياً، ويمكنك استخدامه مباشرة:
const jokes = require('./jokes.json');
console.log(jokes[0].value);
// "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
لكن انتبه إلى نقطتين مهمتين:
- هذه العملية متزامنة
synchronous، أي أنها توقف التنفيذ حتى ينتهي تحميل الملف. - يتم تحميل البيانات في الذاكرة، وإذا تغيّر الملف أثناء تشغيل البرنامج فلن ترى التحديثات إلا بعد إعادة التشغيل.
استخدام fs.readFileSync() مع JSON.parse()
هذه طريقة تقليدية وواضحة، وتعطيك تحكماً أكبر في عملية قراءة الملف وتحليله.
أولاً، استورد وحدة fs:
const fs = require('fs');
ثم اقرأ الملف:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json');
إذا طبعت المتغير jokesFile مباشرة، فسترى ناتجاً من نوع Buffer لأن Node.js لم يتعرف بعد على ترميز الملف.
<Buffer 5b 0a 20 20 7b 0a 20 20 20 20 22 63 61 74 65 67 6f 72 69 65 73 22 3a 20 5b 22 64 65 76 22 5d 2c 0a 20 20 20 20 22 63 72 65 61 74 65 64 5f 61 74 22 3a ... 788 more bytes>
لذلك يجب تمرير الترميز utf8:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
بعدها تصبح البيانات نصاً عادياً، ويمكنك تحويلها إلى كائن أو مصفوفة باستخدام JSON.parse():
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
const jokes = JSON.parse(jokesFile);
console.log(jokes[0].value);
// "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
هذه الطريقة مفيدة عندما تحتاج إلى إعادة قراءة الملف بعد تغيّره. ويمكنك تبسيطها عبر دالة صغيرة:
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');
لكن بما أنها غير متزامنة، فيجب التعامل مع النتيجة داخل دالة callback:
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!');
وسيظهر في وحدة التحكم ما يشبه التالي:
This will run first!
Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris.
هذه الطريقة أفضل عند التعامل مع ملفات كبيرة نسبياً، لأنها لا تعطل بقية الكود أثناء القراءة. ومع ذلك، فهي في النهاية تقوم بتحميل الملف كاملاً في الذاكرة، لذلك إن كان حجم البيانات ضخماً جداً، فقد تكون streams خياراً أفضل.
كيفية استخدام JSON.stringify() في Node.js
كما هو الحال في المتصفح، يمكنك في Node.js تحويل الكائنات أو المصفوفات إلى نص JSON بسهولة:
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));
// {"categories":["dev"],"value":"Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."}
تظهر أهمية هذه الخطوة عند إنشاء استجابات API أو حفظ البيانات النصية أو إرسالها إلى خدمات خارجية.
متى تستخدم JSON.parse() ومتى تستخدم JSON.stringify()؟
| الحالة | الدالة المناسبة | النتيجة |
|---|---|---|
استقبال نص بصيغة JSON |
JSON.parse() |
تحويله إلى كائن أو مصفوفة في JavaScript |
إرسال كائن إلى API |
JSON.stringify() |
تحويله إلى نص صالح للنقل |
قراءة ملف .json في Node.js |
JSON.parse() بعد القراءة |
استخدام البيانات برمجياً |
| تخزين كائن كنص | JSON.stringify() |
حفظه أو إرساله بسهولة |
أفضل الممارسات عند التعامل مع JSON
- تأكد دائماً من صحة صيغة
JSON، خصوصاً علامات الاقتباس والفواصل. - استخدم
try...catchعند الاعتماد علىJSON.parse()إذا كان المصدر غير مضمون. - لا تستخدم
require()مع ملفات تتغير باستمرار إلا إذا كنت تدرك أثر التخزين المؤقتcache. - عند إرسال بيانات إلى
API، اضبط الترويسةContent-Typeعلىapplication/json. - اختر الطريقة المتزامنة أو غير المتزامنة بحسب حجم الملف وطبيعة التطبيق.
الخلاصة التقنية
يُعد فهم JSON من المهارات الأساسية لأي مطور JavaScript. فإذا كنت تستقبل بيانات من واجهة برمجية فستحتاج غالباً إلى JSON.parse() أو إلى .json() مع fetch()، أما إذا كنت ترسل بيانات أو تحفظها كنص فستعتمد على JSON.stringify(). ومن الناحية التقنية، اختيار طريقة القراءة في Node.js يجب أن يعتمد على حجم الملف، وحاجة التطبيق إلى الأداء، ومدى تغيّر البيانات أثناء التشغيل. كلما فهمت الفرق بين النص والبيانات القابلة للاستخدام، أصبح تعاملك مع API والملفات المحلية أكثر احترافية وموثوقية.