JSON و JSONP
۱۶ اردیبهشت ۱۳۸۹ ساعت ۱۲:۳۹
طراحی وب
معرفی JSON و JSONP که چی هستند و به چه درد میخورند
مقدمه: "اطلاعات" دارای ماهیت فیزیکی نیست و هر روشی برای نگهداری و انتقالش قراردادی است. در فضای وب هم برای انتقال اطلاعات روشهایی قرارداد شده که اگر مبدا یا فرستنده اطلاعات رعایت کنه، مقصد یا گیرنده کاملا میتونه درکش کنه.
نمونه: من یه لیست از دانش آموزهای یک کلاس دارم به همراه نمره اشون. می خوام به تو بدم که ببینی.
چند مدل می تونم این لیست رو درست کنم؟ یک مدل اینه که اسم هرکس رو می نویسم و نمره اش رو جلوش می نویسم و اسم بعدی در خط بعدی (مثل لیست نمراتی که هممون سراغ داریم). یک مدل اینه که همه رو پشت سر هم می نویسم یعنی اسم دانش آموز، بلافاصله نمره اش، یک نقطه و اسم بعدی. یک مدل دیگه اینکه یه فرمول اختراع می کنم و لیست رو براساس اون فرمول میچینم که لیستم به یک چیز عجیب غریب و غیرقابل فهم تبدیل میشه و برای اینکه بفهمم فلان دانش آموز نمره اش چنده باید از طریق همون فرمول عمل کنم. و ....
نمیشه گفت چند تا راه برای این کار وجود داره. ولی همه از لیست مدل زیرهم استفاده می کنند چون طبق یک قرارداد نانوشته است و همه ازش سر درمیارند.
در دنیای کامپیوتر هم، انتقال اطلاعات واقعا مهم و حیاتیه و نیاز به قراردادهای اینچنینی کاملا لازمه. یه سری آدم نسبتا بیکار دور هم جمع میشن و فرمتهایی رو پیشنهاد و تعریف و معرفی می کنند تا همه ازشون استفاده کنند. از معروفترین فرمتهای انتقال اطلاعات در وب XML و JSON هست.
اگر نمی دونی XML دقیقا چیه:
HTML یک فرمت خوب برای دسته بندی متن بوده و با ایده گرفتن ازش، فرمت XML رو پیشنهاد کردند که مخفف Xtendable Hypertext Language یعنی زبان نشانه گذاری توسعه یافته است. اومدند گفتند که اطلاعات رو توسط تگهایی شبیه HTML مرتب کنیم. مثلا می خوایم لیست دانش آموزها رو با فرمت XML بسازیم:
<xml> <studentsdata> <classdata> <name>A1</name> <teacher>Mr. Folani</teacher> </class> <list> <student> <firstname>Amir</firstname> <lastname>Hossein</lastname> <score>18</score> </student> <student> <firstname>Amir Hossein</firstname> <lastname>Hodjati</lastname> <score>19</score> </student> <student> <firstname>Amir Hossein</firstname> <lastname>Hodjati Pour</lastname> <score>20</score> </student> </list> </studentsdata>حالا این چه فایده ای داره؟ فایده اش اینه که من اگر هزار تا لیست اینجوری داشته باشم، می تونم توسط فرمتی که دارم استفاده می کنم، اطلاعاتش رو بازیابی کنم. مثلا اینجا اطلاعات همه دانش آموزها داخل تگ list قرار گرفته. اطلاعات کلاس داخل تگ classdata، اطلاعات هر دانش آموز داخل تگ student و به همین ترتیب. این رو من خودم می دونم و میفهم و می تونم واسه هرکس دیگه ای تو همین دو خط توضیح بدم تا بفهمه.
لازم به گفتن هست RSS فرمتی استاندارد برای داده های سایته، توسط XML ولی با تگهای مشخص. یعنی توی RSS تگ title باید حاوی عنوان مطلب باشه تا همه بتونن بازیابیش کنند. کلی قصه گفتم که فایده این فرمتها رو بگم. از بین چنین فرمتهایی (که تعدادشون کم نیست)، JSON یک نمونه خیلی خاص می تونه باشه.
JSON مخفف JavaScript Object Notation است یعنی نشانه گذاری توسط اشیاء جاوااسکریپت. JSON در واقع شیء و آرایه جاوااسکریپت هست که وقتی متن رو به اون شکل مرتب کنیم، در زبان جاوااسکریپت میشه دوباره به Object یا شیء تبدیل کرد و استفاده کرد. مثلا می خوایم اطلاعات XML بالا رو به JSON تبدیل کنیم:
{
classdata: {
name: "A1",
teacher: "Mr. Folani"
},
list: [
{
firstname: "Amir",
lastname: "Hossein",
score: "18"
},
{
firstname: "Amir Hossein",
lastname: "Hodjati",
score: "19"
},
{
firstname: "Amir Hossein",
lastname: "Hodjati Pour",
score: "20"
}
]
}
من اطلاعاتم رو به این شکل می نویسم و می تونم بین اسکریپتهام و زبانهای برنامه نویسی ام منتقل کنم. مثلا وقتی این متن که از XML کم حجمتره رو به جاوااسکریپت میبرم و در متغیری به نام data ذخیره می کنم، اینجوری می تونم پردازشش کنم:
var json = eval("(" +data+ ")");
var className = json.classdata.name;
var teacher = json.classdata.teacher;
var firstStudent_score = json.list[0].score;
خوبی JSON اینه فقط توی جاوااسکریپت قابل استفاده نیست و خیلی از زبانها ازش پشتیبانی می کنند. مثلا همین تکه کد بالا در PHP5 به این شکل میشه:
$json = json_decode($data); $className = $json->classdata->name; $teacher = $json->classdata->teacher; $firstStudent_score = $json->list[0]->score;
من وقتی بین اسکریپتهام انتقال اطلاعات زیاد دارم، بجای آرایه از JSON استفاده می کنم و برای AJAX، اگر اطلاعاتم متن ساده نباشه، همیشه JSON رو به XML ترجیح میدم چون کار کردن باهاش در جاوااسکریپت خیلی سادست.
و اما JSONP،
محدودیتی در استفاده از AJAX وجود داره و اون عدم دسترسی به اطلاعاتی هست که از یک آدرس دیگه اومده. مثلا من میخوام در سایتم پیش بینی وضعیت آب و هوا رو از سایت یاهو بصورت AJAX داشته باشم. روشهایی برای این کار وجود داره ولی روش مستقیم ممکن نیست که من Request رو به سایت یاهو بفرستم و Response بگیرم. برای چنین استفاده هایی، JSONP معرفی شده.
JSONP مخفف JOSN with Padding یعنی استفاده از JSON با واسطه است (این ترجمه مفهومی اش هست نه لغوی) و در واقع یک حقه و ترفنده که با همکاری سایت مبدا و مقصد انجام میشه. به این ترتیب که مثلا من میخوام دمای تهران رو از سایت یاهو بگیرم که به شکل JSON زیر این اطلاعات رو میده و از JSONP پشتیبانی می کنه:
{
city: "Tehran",
temperature: "27",
scale: "Celsius"
}
حقه به این صورت انجام میشه که من یک تابع جاوااسکریپت در صفحه میسازم که این شیء رو بصورت پارامتر میگیره. مثلا تابع زیر:
function getTemp(jsonp) {
alert( jsonp.temperature );
}
اصل کار اینجوری انجام میشه که سایت مبدا (همون آب و هوای یاهو)، نام این تابع رو میگیره و این خروجی رو میده:
getTemp({
city: "Tehran",
temperature: "27",
scale: "Celsius"
});
حالا تصور کن که من این سایت رو توسط تگ script فراخوانی کرده باشم یعنی شبیه این:
<script type="text/javascript">
function getTemp(jsonp) {
alert( jsonp.temperature );
}
</script>
<script type="text/javascript"
src="http://weather.yahoo.com/tehran/?callback=myTemp">
</script>
من توی src فرضی بالا، نام تابع رو به آدرسی که قراره JSON رو بده ارسال می کنم و خروجی این آدرس به شکل جاوااسکریپت فورا اجرا میشه و من دمای تهران رو میبینم.
کد زیر دقیقا مثل کد بالا عمل می کنه با این تفاوت که در کد زیر، JSON رو بصورت استاتیک خودمون داریم میدیم و در بالا داره بصورت داینامیک از یک سایت Extrenal میاد:
<script type="text/javascript">
function getTemp(jsonp) {
alert( jsonp.temperature );
}
</script>
<script type="text/javascript">
getTemp({
city: "Tehran",
temperature: "27",
scale: "Celsius"
});
</script>
همونطور که واضحه سایت مبدا باید JSONP رو پشتیبانی کنه یعنی نام تابع من رو بگیره و خروجی JSON خودش رو به تابع من بده.
حالا این چه ربطی به AJAX داشت؟ ما می تونیم در کدهای مربوط به AJAX، تگ script رو بسازیم، اجرا کنیم، خروجی بگیریم. کاملا شبیه AJAX. این سناریو رو فرض کن که توی سایتت، یک بخش آب و هوا داری. کاربر شهر رو انتخاب می کنه و تو دما رو توسط کد و آدرس فرضی زیر نمایش میدی:
function getTemp(jsonp) {
alert( jsonp.temperature );
}
function getCity(city) {
var script = document.createElement('script');
script.type ="text/javascript";
script.src = "http://weather.yahoo.com";
script.src += "/" +city+ "/?callback=getTemp";
// http://weather.yahoo.com/shiraz/?callback=getTemp
document.getElementsByTagName('head')[0].appendChild(script);
}
خلاصه کار کردن با JSON خیلی لذتبخشه و من واقعا دوستش دارم!
پی نوشت: یکی دوستان به نام eAmin که من ایشون رو از سایت Barnamenevis.org میشناسم. به یکی از نکته های جاافتاده اشاره کردند که خوب دونستم با قدردانی از ایشون، اینجا بهش اشاره کنم:
من گفتم برای decode کردن JSON در جاوااسکریپت میتونیم از تابع eval استفاده کنیم و این توابع همه کدهای جاوااسکریپت رو اجرا می کنه! این یعنی برای گرفتن JSON باید کاملا حواسمون به ورودی های ناخواسته و مخرب باشه و بهتره که بجای تابع Eval از توابع استاندارد و مطمئن استفاده کنیم.
در سایت JSON.org می تونی توابع استاندارد تحت زبانهای مختلف و اطلاعات بیشتر کسب کنی.


Google Chrome
تو چی فکر می کنی؟