امروز قراره موضوعی رو پوشش بدم که احساس میکنم به یه بخش بزرگی از ابزار هر توسعه دهنده تبدیل شده، موضوع بحث امروز توانایی بارگیری و دستکاری جیسون JSON توسط AJAX است. امروزه سایت های زیادی علاوه بر فیدهای RSS داده های جیسون رو هم به اشتراک میذارن.

مقاله امروز ما شامل:

  • JSON چیست؟
  • دلیل اهمیت جیسون چیه؟
  • نحوه استفاده از جیسون در یک پروژه
  • آشنایی با خطای جیسون
  • نحوه رفع خطای JSON

شما چه قرار باشه یه توسعه دهنده بشین چه نه، دونستن یه سری اصول درباره جیسون و دلیل اهمیتش یه ایده خوبی براتون به حساب میاد.

بریم که با اصطلاحات جدید بیشتر آشنا بشیم:

JSON چیست؟

JSON کوتاه شده عبارت JavaScript Object Notation است و یه راهی برای ذخیره کردن اطلاعات به صورت سازمان یافته و با دسترسی آسونه. به طور خلاصه، مجموعه‌ای از داده هایی که برای انسان قابل خوندنه رو بهمون میده و ما میتونیم با یه روش کاملاً منطقی به اونها دسترسی پیدا کنیم.

المان‌های مهم در جیسان

تو JSON یه سری المان مهم وجود داره که برای خوندن ادامه مقاله باید باهاشون آشنا باشین، این المان‌ها عبارتند از:

  • ([)Array: تو یه فایل JSON کروشه ( [ ) نشون دهنده یه ردیف JSON است.
  • ({ )Objects: تو یه فایل JSON این علامت (}) نشون دهنده یه آبجکت JSON است.
  • Key: یه آبجکت JSON کلیدیه که فقط یه رشته است. جفت‎های کلید/مقدار (value/key) یه آبجکت JSON رو تشکیل میدن.
  • Value: هر کلید میتونه یه مقداری داشته باشه که این مقدار می تونه رشته، integer یا double یا غیره باشه.

نحوه نوشتن در JSON

برای نوشتن جیسان باید یه سری قواعد رو بدونین که ما به طور خیلی خلاصه اینجا بهتون گفتیم:

  • داده‌ها در جفت‌هایی بصورت نام/مقدار (name/value) قرار می‌گیرن.
  • داده‌ها با علامت کاما از هم جدا می‌شن.
  • پرانتز‌ها اشیاء رو نگه می‌دارن.
  • براکت‌ها آرایه‌ها رو نگه می‌دارن.

ذخیره سازی داده های جیسون به چه شکله؟

میخوام نحوه کار این سیستم رو خیلی ساده براتون توضیح بدم، به کد زیر که شامل اطلاعات من میشه نگاه کنین:


            var Fateme = {
"age" : "23",
"hometown" : "Isfahan",
"gender" : "female"
};
                            

این کار یه شی ایجاد میکنه که ما با استفاده از متغیر JSON میتونیم به اون دسترسی پیدا کنیم. با قرار دادن مقدار متغیر در یک براکت {} نشون میدیم که این مقدار یه شیء است. در داخل این شی میتونیم با استفاده از جفت هایی به صورت “Name” و “Value” (اسم/مقدار) که با کاما از هم جدا میشن، ویژگی یه مورد رو بیان کنیم. برای دسترسی به اطلاعات ذخیره شده در جیسون میتونیم به سادگی به نام ویژگی مورد نظر خودمون مراجعه کنیم. مثلاً برای دسترسی به اطلاعات من، میتونیم از قطعه‌های زیر استفاده کنیم:


            document.write('Fateme is ' Fateme.age); // Output: Fateme is 23
document.write('Fateme is a ' Fateme.gender); // Output: Fateme is a female
                            

ذخیره داده های JSON در آرایه‌ها

یه مثال یکم پیچیده‌تر شامل ذخیره دو نفر در یه متغیر است. برای انجام دادن این کار، چندتا شی رو در براکت ها محصور میکنیم، که هر کدوم از اونها نشون دهنده یه آرایه است. به عنوان مثال اگه نیاز داشتم که اطلاعات مربوط به خودم و دوستم رو در یه متغیر درج کنم، میتونم به شکل زیر عمل کنم:


            var Friends= [{
"name" : "Fateme",
"age" : "23",
"gender" : "female"
},
{
"name" : "Matin",
"age" : "22",
"gender" : "male"
}];
                            

برای دست یابی به این اطلاعات باید به فهرست آرایه شخص موردنظر خودمون دسترسی پیدا کنیم، مثلاً برای اطلاعات ذخیره شده در خانواده من از قطعه زیر استفاده میکنیم:


            document.write(family[1].name); // Output: Farid
document.write(family[0].age); // Output: 25
                            

ذخیره کردن داده های JSON به روش Nesting

یه روش دیگه برای ذخیره کردن چند نفر در متغییر، روش Nesting است. برای این کار باید شبیه زیر عمل کنین:


            var Friends = {
"fateme" : {
"name" : "Fateme Amooshahi",
"age" : "23",
"gender" : "female"
},
"Matin" : {
"name" : "Matin Roozbahani",
"age" : "22",
"gender" : "male"
}
}
                            

دستیابی به اطلاعات در اشیا نست شده، درک ساده‌تری داره. برای دستیابی به اطلاعاتی که در شی وجود داره، میتونین از قطعه زیر استفاده کنین:


            document.write(Friends.Fateme.name); // Output: Fateme Amooshahi
document.write(Friends.Matin.age); // Output: 22
document.write(Friends.Fateme.gender); // Output: female
                            

JSON و آرایه‌های ذخیره شده میتونن در صورت لزوم برای ذخیره هرچه بیشتر داده ها با هم ترکیب بشن.

چرا JSON اهمیت داره؟

با ظهور سایت های مجهز به AJAX این که سایت ها بتونن داده ها رو به سرعت و ناهمزمان بارگیری کنن، یا در پس زمینه بدون تاخیر در ارائه صفحه بارگذاری داده ها رو انجام بدن یه امر مهم تلقی شد. تغییر محتوای یه عنصر خاص در بین Layout ها، بدون درخواست رفرش کردن صفحه، یه انفاق خیلی هیجان انگیزی برای برنامه‌های ما بود.

بخاطر محبوبیت و سهولت در استفاده از رسانه های اجتماعی، خیلی از سایت ها به مطالب ارائه شده توسط شبکه هایی مثل توییتر و غیره اعتماد میکردن. این سایت ها فیدهای RSS ارائه میدن که وارد کردن و استفاده از اونها بر روی سرور خیلی آسونه اما اگه سعی کنیم اونها رو با AJAX بارگذاری کنیم، به یه دیوار میخوریم!! ما فقط میتونیم یه فید RSS یی رو بارگذاری کنیم که اون رو از دامنه مشابهی که میزبانی میشه، درخواست کنیم.

تلاش برای بارگیری فید RSS در حساب Flicker از طریق متد ()jQuery’s $.ajax نتیجه‌ش ارور جاوااسکریپت زیر شد:


            [Exception... "Access to restricted URI denied" code: "1012"
nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)"
location: "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js Line: 19"]
                            

پس JSON به ما اجازه میده تا بر مشکل دامنه متقابل cross-domain غلبه کنیم، چون ما دیگه میتونیم از متدی به اسم JSONP استفاده کنیم که از یه تابع برگشتی برای ارسال داده JSON به دامنه ما استفاده میکنه. این قابلیتیه که جیسان رو خیلی فوق العاده میکنه چون حالا میتونیم از درهایی عبور کنیم که تا چندوقت پیش دیوار بودن!

خوبه که بدونین جی ‌سان بیشتر برای سریال کردن و انتقال ساختمان داده‌ها از طریق ارتباط شبکه‌ای به ‌کار گرفته میشه. بیشترین استفاده اون هم برای انتقال داده‌ها بین یه کارساز و یه برنامه وبی به‌عنوان جایگزینی برای اکس‌ام‌ال XML است.

اگه با php برنامه نویسی میکنین، کافیه که از تابع‌هایی که برای JSON در نظر گرفته شدن استفاده کنین.

چطوری JSON رو در یک پروژه بارگذاری کنیم؟

یکی از ساده‌ترین راه‌های بارگذاری داده های جیسان در برنامه‌های وب استفاده از روش ()ajax.$ موجود در کتابخونه jQuery است. سهولت بازیابی اطلاعات براساس سایتی که داده ها رو ارائه میده متفاوت خواهد بود. یه مثال ساده برای این امر به شرح زیره:


            $.ajax(
type:'GET',
url:"http://example.com/users/feeds/",
data:"format=json&id=123",
success:function(feed) {
document.write(feed);
},
dataType:'jsonp'
);
                            

این مثال جدیدترین آیتم‌های فید در فرمت JSON رو درخواست میکنه و اونها رو به مرورگر منتقل میکنه. بدیهیه که ما نمیخوایم داده های JSON خام رو به مرورگر منتقل کنیم، اما این مثال مبانی بارگذاری جی سان رو از یه منبع خارجی نشون میده.

یک مثال عملی: بارگیری جریان‌های Flicker با JSON و jQuery

برای نشون دادن نحوه عملکرد جیسون، یه مثال از دنیای واقعی براتون آماده کردیم. میخوایم عکس‌ها رو از Flicker با استفاده از jQuery و نسخه JSON از آخرین فید عکس Flicker بارگذاری کنیم.

مرحله اول: درخواست AJAX تولید کنین

دسترسی به فیدهای Flicker نسبتاً کار آسونیه، همه کاربران یه شماره شناسه منحصر به فرد دارن که ما اون رو به عنوان یه بخشی از درخواست به این URL میفرستیم:

http://api.flickr.com/services/feeds/photos_public.gne

درخواستی که باید ارسال کنیم جدیدترین عکس‌ها رو به همراه درخواست پاسخ با فرمت JSON، از کاربر مورد نظر درخواست میکنه. درخواستی که باید ارسال کنیم به شرح زیره:

id=XXXXXXXX@NXX&lang=en-us&format=json&jsoncallback=?

تو مثال بالا XXXXXXXX@NXX باید با شناسه کاربر جایگزین بشه، ما یه تابع مینویسیم، بنابراین شناسه کاربر به عنوان شناسه‌ای به نام flickerID منتقل میشه. به عملکر ما ()loadFliker میگن. بیایین تابعی رو ایجادکنیم که پاسخ جیسان ما رو بارگیری میکنه:


            function loadFlickr(flickrid)
{
$('#feed').html('<span><img src="/blog/images/lightbox-ico-loading.gif" alt=""></span>');
$.ajax({
type:'GET',
url:"http://api.flickr.com/services/feeds/photos_public.gne",
data:"id="+flickrid+"&lang=en-us&format=json&jsoncallback=?",
success:function(feed) {
// Do something with the response
},
dataType:'jsonp'
});
}
                            

داده های برگشتی جیسون مثل این خواهد بود (یادتون باشه که ما همه عکس‌های برگشتی به جز یکی از اونها رو برای کوتاه شدن مثالمون حذف کردیم):


            ({
"title": "Uploads from ennuidesign",
"link": "http://www.flickr.com/photos/ennuidesign/",
"description": "",
"modified": "2009-03-17T03:53:36Z",
"generator": "http://www.flickr.com/",
"items": [
{
"title": "This Is How You Get People to Talk About You",
"link": "http://www.flickr.com/photos/ennuidesign/3361269251/",
"media": {"m":"http://farm4.static.flickr.com/3470/3361269251_9c55e6dc24_m.jpg"},
"date_taken": "2009-03-16T21:53:36-08:00",
"description": "<p><a href="http://www.flickr.com/people/ennuidesign/">ennuidesign</a> posted a photo:</p> <p><a
title="This Is How You Get People to Talk About You" href="http://www.flickr.com/photos/ennuidesign/3361269251/"><img
src="http://farm4.static.flickr.com/3470/3361269251_9c55e6dc24_m.jpg" alt="This Is How You Get People to Talk About You"
width="240" height="180"></a></p> <p>A guy I know, Trevor Gnauck, made this custom pint glass for me. He runs a company
called <a href="http://www.bluedragonllc.com/">Blue Dragon Custom Laser Engraving</a> with his family, and he had no reason
whatsoever to do anything nice for me.<br> <br> He did, though, and look how cool that is! I can now drink a beer out of my own
likeness.<br> <br> I know it wasn't his intention, but this is how you get people to talk about you. Unprovoked kindness will
always inspire kindness in return, and the power of a kind gesture should never be overlooked.</p>",
"published": "2009-03-17T03:53:36Z",
"author": "nobody@flickr.com<script type="text/javascript">
/* <![CDATA[ */
(function(){try{var s,a,i,j,r,c,l=document.getElementById("__cf_email__");a=l.className;if(a
{s='';r=parseInt(a.substr(0,2),16);for(j=2;a.length-j;j+=2
{c=parseInt(a.substr(j,2),16)^r;s+=String.fromCharCode(c);}s=document.createTextNode(s);l.parentNode.replaceChild(s,l);}}cat
h(e){}})();
/* ]]> */
</script> (ennuidesign)",
"author_id": "29080075@N02",
"tags": "gift ennuidesign trevorgnauck bluedragoncustomlaserengraving"
}
// The rest of the photo entries go here...
]
})
                            

مرحله دوم: داده های JSON رو پردازش کنین

کاری که ما میخوایم انجام بدیم، نمایش یه تصویر کوچیک از ۱۶ عکس آخره که به نمایشگر سایز متوسط تصویر لینک میشه. Flicker JSON یکم ممکنه گیج کننده باشه و لینک مستقیمی با نسخه ریز عکس‌های ما فراهم نکنه، بنابراین برای رسیدن به چیزی که میخوایم مجبوریم از ترفندهایی استفاده کنیم.

لحظه ورود هر عکس تو یه آرایه‌ای به نام آیتم ذخیره میشه که از این طریق ما به AJAX Call با استفاده از feed.item دسترسی پیدا میکنیم. برای دسترسی به اطلاعات مربوط به هر ورودی، آیتم‌ها رو حلقه میکنیم (Loop) تا زمانی که یا به آخرین عکس موجود یا به همه ۱۶ تا عکس برخورد کنیم.

اصلاح عملکرد و تنظیم حلقه به شکل زیر انجام میشه:


            function loadFlickr(flickrid)
{
// Display a loading icon in our display element
$('#feed').html('<span><img src="/blog/images/lightbox-ico-loading.gif" alt=""></span>');
// Request the JSON and process it
$.ajax({
type:'GET',
url:"http://api.flickr.com/services/feeds/photos_public.gne",
data:"id="+flickrid+"&lang=en-us&format=json&jsoncallback=?",
success:function(feed) {
// Create an empty array to store images
var thumbs = [];
// Loop through the items
for(var i=0, l=feed.items.length; i < l && i < 16; i)
{
// Process each image
}
// Display the thumbnails on the page
},
dataType:'jsonp'
});
}
                            

عنصر مورد نظر ما عنصر “m” است که در عنصر “media” ذخیره شده. با استفاده از feed.items[i].media.m میتونین به حلقه دسترسی پیدا کنین.

ما میخوایم یه عبارت منظم رو روی این مقدار اجرا کنیم تا هم مسیر تصویر متوسط و هم مسیر تصویر کوچیک رو بگیریم که اونها رو تو یه لینک تصویر کوچیک جمع میکنیم! سپس ما HTML تازه مونتاژ شده رو به آرشیو عکس‌های کوچیکی که ایجاد کردیم، منتقل میکنیم. بعد از این که حلقه رو تموم کردیم، همه تصاویر رو در یه رشته HTML ترکیب میکنیم و محتوای عنصر نمایش خودمون رو با تصاویر کوچیک بارگذاری شده جایگزین میکنیم پس بیاین این قابلیت رو به اسکریپت خودمون اضافه کنیم:


            function loadFlickr(flickrid)
{
// Display a loading icon in our display element
$('#feed').html('<span><img src="/blog/images/lightbox-ico-loading.gif" alt=""></span>');
// Request the JSON and process it
$.ajax({
type:'GET',
url:"http://api.flickr.com/services/feeds/photos_public.gne",
data:"id="+flickrid+"&lang=en-us&format=json&jsoncallback=?",
success:function(feed) {
// Create an empty array to store images
var thumbs = [];
// Loop through the items
for(var i=0, l=feed.items.length; i < l && i < 16; i)
{
// Manipulate the image to get thumb and medium sizes
var img = feed.items[i].media.m.replace(
/^(.*?)_m.jpg$/,
'<a href="/blog/$1.jpg"><img src="/blog/$1_s.jpg" alt=""></a>'
);
// Add the new element to the array
thumbs.push(img);
}
// Display the thumbnails on the page
$('#feed').html(thumbs.join(''));
// A function to add a lightbox effect
addLB();
},
dataType:'jsonp'
});
}
                            

توجه کنین که ما همچنین یه تابع به اسم () addLB رو به انتهای این عملکرد اضافه کردیم، این کار اثر lightbox رو به عکس‌های کوچیک ما اضافه میکنه که زیبایی شناسی خیلی خوبه!

مرحله سوم: عملکرد ما را فراخوانی کنین

تو این مرحله آماده‌ایم که عملکرد خودمون رو فراخوانی کنیم. برای بارگذاری جریان Flicker باید عملکرد خودمون رو به شرح زیر فراخوانی کنیم:

loadFlickr(“29080075@N02”);

نمونه پست شده photostraem چندتا کاربر رو وارد باکس میکنه بدون این که به رفرش کردن صفحه نیاز باشه. به کد منبع نسخه نمایشی نگاه کنین تا متوجه بشین که این کار چطوری انجام میشه.

یادتون باشه که این نسخه برای نشون دادن نحوه بارگذاری داده های JSON بود و نه نحوه اجرای کد برای فراخوانی عملکرد! فراخوان‌های جاوا اسکریپت به صورت درون خطی هستن که نباید از اونها تو یه اسکریپت استفاده کرد.

مزیت JSON چیست؟

جیسون نخستین قالبی نیست که از جفت‌های خصوصیت-کلید برای تبادل داده‌ها بر روی اینترنت استفاده می‌کنه. فناوری‌های مختلفی تو این زمینه وجود دارن که ممکنه حتی بعضی از اونها مثل XML رو هم بشناسین. جیسون و ایکس ‌ام ‌ال تقریباً عین همدیگه کار میکنن.

پس به نظرتون چرا باید جیسون رو به ایکس‌ ام ‌ال ترجیح بدیم؟

در وب امروز بارگذاری asynchronous (غیر همزمان و یا در مواردی نامتقارن نامیده میشه) داده‌ها خیلی چیز مهمیه. به عبارتی دیگه صفحه‌های وب می‌خوان بتونن داده‌ها رو بدون نیاز به بارگذاری مجدد کل صفحه به کاربر ارسال کنن. نتیجه چنین امکانی، ایجاد تجربه مرور روان‌تر و مطلوب‌تر برای کاربر است. حالا این جیسون برای ارسال و دریافت غیر همزمان داده‌ها یه روش خیلی عالیه، چرا؟ خب معلومه چون ساده است پس استفاده از اون کار راحتیه!

اما خب ایکس‌ ام ‌ال هم همین کار رو انجام می‌ده! پس چرا انقدر یه سری‌ها واسه جیسون سر و دست میشکنن؟!!

یکی از پاسخ‌های ممکن به این سؤال شاید بخاطر اسم جیسون باشه! نمادگذاری اشیای جاوا اسکریپت. جیسون معمولاً همراه با جاوا اسکریپت شناسایی می‌شه که یکی از رایج‌ترین زبان‌های برنامه‌نویسی دنیا است. از اونجایی که جیسون زیرمجموعه‌ای از جاوا اسکریپت است، برای کسایی با جاوا اسکریپت آشنا هستن، نیازی به یادگیری موارد زیادی در زمان استفاده از جیسون وجود نخواهد داشت.

یه دلیل دیگه برای این محبوبیت جیسون اینه که خوانایی بالاتری نسبت به ایکس‌ام‌ال داره. البته وقتی یکم با ایکس‌ام‌ال کار کنین، استفاده از اون رو هم راحت یاد میگیرین؛ اما نگاهی گذرا به فایل ایکس‌ام‌ال کاربر رو با انبوهی از تگ‌ها و موارد توضیحی روبرو می‌کنه. اما به جاش جیسون حسابی تر و تمیزتره و افراد مبتدی خیلی راحت‌تر درکش می‌کنن. از طرف دیگه با انواع داده‌های مقدماتی خودتون، تا حدودی انعطاف‌پذیری بیشتری ارائه میده.

این هم جیسون و نحوه استفاده از اون! حالا شما به ما بگین ببینم آیا تا حالا از JSON استفاده کردین؟ چه مشکلی با این قالب داشتین؟ میتونین هر تجربه و یا سوالی که در این باره دارین رو از طریق کامنت‌ها با ما در میون بذارین.