JSON چیست و چرا در وب اینقدر استفاده میشود؟
شرح عملی JSON طبق RFC 8259 و MDN: انواع داده، تفاوت کاربردی با XML، دامهای عدد و تاریخ و Unicode، و نمونهٔ کوتاه parse/stringify.
SE
13 min readSoheil Ebrahimpour
Founder & product engineer

وقتی API موجودی فروشگاه پاسخ میدهد، معمولاً یک متن میفرستد که هم انسان میتواند بخواند و هم تقریباً هر زبان برنامهنویسی میتواند به ساختار بومی تبدیل کند. آن متن اغلب نشانهگذاری شیء جاوااسکریپت (JavaScript Object Notation یا JSON) است. محبوبیتاش از «زیبایی نحو» کمتر است تا از حداقل بودن، استقلال از زبان، و حضور آماده در مرورگر و سرور.
RFC 8259 — استاندارد ردگیری IETF به تاریخ دسامبر ۲۰۱۷ که RFC 7159 را منسوخ میکند — JSON را قالب تبادل دادهٔ سبک، متنی و مستقل از زبان میداند که از استاندارد زبان ECMAScript مشتق شده و مجموعهٔ کوچکی از قواعد قالببندی برای نمایش قابلحمل دادهٔ ساختیافته تعریف میکند. MDN همان را به زبان آموزش وب میگوید: قالب متنی استاندارد بر اساس نحو شیء جاوااسکریپت، رایج برای ارسال داده بین سرور و کلاینت.
این صفحه انواع، محدودیت نحو، دلیل رواج در وب، مقایسهٔ عملی با XML، و دامهای عدد و تاریخ و یونیکد را جمع میکند. JSON جایگزین API نیست؛ بدنهٔ رایجی است که قرارداد ۰۳۶ روی آن سوار میشود و REST ۰۳۷ اغلب با آن بازنمایی میفرستد.
اگر یک جمله کافی است: JSON متنی است که شیء، آرایه و چهار نوع بدوی را جابهجا میکند؛ تاریخ و عدد خیلیبزرگ را خودش نمیفهمد و باید در قرارداد جدا قفل شوند.

پاسخ کوتاه
طبق RFC 8259، JSON چهار نوع بدوی دارد — رشته، عدد، بولی، null — و دو نوع ساختیافته: شیء (مجموعهٔ نام/مقدار) و آرایه (دنبالهٔ مرتب). متن JSON روی شبکه باید UTF-8 باشد. نوع رسانه application/json است. در جاوااسکریپت، JSON.parse متن را به مقدار بومی تبدیل میکند و JSON.stringify برعکس.
- کلید شیء باید رشتهٔ داخل گیومهٔ دوتایی باشد؛ کامای پایانی و توضیح مجاز نیست.
- عدد Infinity و NaN مجاز نیستند؛ دقت اعشاری محدود به واقعیت IEEE 754 است.
- تاریخ نوع جدا ندارد؛ معمولاً رشتهٔ ISO میفرستید.
- XML هنوز برای سند حاشیهنویسیشده و برخی تبادلهای سازمانی rational است؛ برای API وبِ سبک، JSON اصطکاک کمتری دارد — نه «همیشه بهتر».
JSON ساده است؛ ساده بودن یعنی خیلی چیزها بیرون از دستور زبان میمانند و باید در قرارداد نوشته شوند.
تعریف استاندارد: RFC 8259 چه میگوید
مقدمهٔ RFC هدف طراحی را حداقل، قابلحمل، متنی، و زیرمجموعهای از جاوااسکریپت اعلام میکند. یک متن JSON یک مقدار سریالشده است. مشخصات قدیمیتر متن را به شیء یا آرایه محدود میکردند؛ ۸۲۵۹ صریح میگوید یک مقدار تنها — رشته، عدد، true — هم JSON معتبر است. پیادهسازیهایی که فقط شیء یا آرایه تولید میکنند همچنان با همه همعمل میکنند.
شیء داخل آکولاد مجموعهای نامرتب از جفت نام/مقدار است. نام رشته است. RFC میگوید نامها SHOULD یکتا باشند. اگر تکراری باشند رفتار غیرقابلپیشبینی است: بعضی فقط آخری را میگیرند، بعضی خطا میدهند، بعضی همه را نگه میدارند. برای همعملی، نام تکراری نفرستید. ترتیب اعضا هم تضمین دیدهشدن برای همهٔ کتابخانهها نیست.
آرایه داخل کروشه دنبالهای مرتب است. لازم نیست اعضا همنوع باشند. فضای خالی بیمعنا فقط قبل یا بعد از شش نویسهٔ ساختاری مجاز است: [ ] { } : , و فقط فاصله، تب، خط جدید و بازگشتسرسطر.
RFC 8259 با ECMA-404 همتراز است. تفاوت عملی: ECMA-404 بعضی رویهها را اجازه میدهد که IETF برای همعملی بیشینه توصیه به پرهیز میکند. اگر برای وب عمومی تولید میکنید، سمت سختگیر RFC را بگیرید.
انواع داده و محدودیت نحو
واژهنامهٔ MDN همان شش ظرفیت را تکرار میکند: عدد، بولی، رشته، null، آرایه، شیء ساختهشده از اینها. JSON بهطور بومی تابع، عبارت منظم، تاریخ، Set و Map را نمایندگی نمیکند. اگر به نوع اضافه نیاز دارید، هنگام سریال و قبل از و سریال باید تبدیل کنید.
صفحهٔ آموزشی MDN محدودیتهایی میگذارد که در عمل بیشترین SyntaxError را میسازند:
- رشته فقط با گیومهٔ دوتایی؛ تکگیومه JSON نیست.
- نام ویژگی باید رشتهٔ گیومهدار باشد.
- عدد فقط نماد دهدهی؛ پیشصفر مجاز نیست (طبق گرامر RFC).
- undefined و NaN و Infinity در JSON نیستند.
- کامای پایانی بعد از آخرین عضو ممنوع است.
- توضیح (comment) وجود ندارد.
این سختگیری همان چیزی است که تولیدکنندهها را قابلاعتماد میکند. RFC به مولد میگوید متن باید دقیقاً مطابق گرامر باشد؛ به تجزیهگر میگوید همهٔ متن منطبق را بپذیرد و مجاز است متن غیر JSON یا افزونه را هم بپذیرد. برای تبادل عمومی، افزونه را در قرارداد ننویسید مگر هر دو طرف همان افزونه را تعهد کنند.
نمونهٔ کوتاه: از متن به شیء و برعکس
MDN دو روش شیء سراسری JSON را اینطور تعریف میکند: parse یک رشتهٔ JSON میگیرد و مقدار جاوااسکریپت برمیگرداند؛ stringify یک مقدار میگیرد و رشتهٔ JSON میسازد. تبدیل رشته به شیء بومی deserialization است؛ مسیر برعکس serialization. مثال آموزشی MDN یک شیء کوچک را رشته میکند:
javascript
const product = { id: 124, name: "چای سبز", inStock: true }; const text = JSON.stringify(product); // text === '{"id":124,"name":"چای سبز","inStock":true}' const again = JSON.parse(text); console.log(again.name); // چای سبز
در شبکه معمولاً مستقیم response.json() از Fetch را میبینید؛ MDN توضیح میدهد این همان parse روی بدنه است. اگر بدنه را با text() گرفتید، خودتان parse کنید. رشتهٔ نامعتبر SyntaxError میدهد. برای فروشگاه: همین شیء میتواند پاسخ GET /products/124 باشد. قرارداد بگوید id عدد است یا رشته؛ مخلوط بیخبر همانجا شروع باگ موجودی است.
stringify تابع و undefined را در شیء حذف میکند و در آرایه به null تبدیل میکند. اگر فیلدی را فرستادید و در خروجی نیست، اول نوع را چک کنید، بعد شبکه را.
چرا وب JSON را اینقدر به کار میبرد
سه دلیل تکراری و قابلراستیآزماییاند، نه اسطورهٔ بازاریابی. اول: مرورگر و جاوااسکریپت تبدیل بومی دارند؛ MDN میگوید این مسئله آنقدر رایج بوده که شیء JSON داخل زبان آمده است. دوم: تقریباً هر محیط سرور — از Python و PHP تا Go و C# — مولد و تجزیهگر دارد؛ خود RFC فهرست بلندی از زبانهایی میآورد که application/json در آنها به کار رفته. سوم: نسبت به XML برای شیء تو در توِ سبک، نویسهٔ کمتری صرف برچسب میکند و با مدل برنامهٔ فرانت (شیء و آرایه) یکی است.
REST و JSON اغلب با هم دیده میشوند چون بازنمایی منبع باید نوعی رسانه داشته باشد و application/json — همان نوع ثبتشده در RFC 8259 — پیشفرض عملی بسیاری از APIهای عمومی است. این یعنی JSON «جزء REST» نیست؛ فقط جفت رایجی است. انتخاب قالب جدا از انتخاب سبک معماری است.
دلیل چهارم عملی: اشکالزدایی. بدنهٔ JSON را میتوان در ابزار توسعهدهنده خواند. این برای تیم مختلط محصول و مهندسی هزینهٔ هماهنگی را کم میکند. تاواناش را در بخش دامها میبینید: خوانا بودن باعث نمیشود عدد بزرگ یا تاریخ درست تفسیر شود.
JSON و XML در سطح عملی
XML سند درختی با نامفضا، ویژگی، و گاهی طرح (XSD) است. برای سندی که حاشیه، مخلوط متن و عنصر، و اعتبارسنجی سازمانی سنگین دارد هنوز rational است. SOAP و بسیاری از تبادلهای بانکی و دولتی همان مسیر مبتنی بر XML را نگه داشتهاند.
JSON نقشهٔ نام/مقدار و فهرست است. نامفضا ندارد. ویژگی جدا از عنصر ندارد. توضیح ندارد. طرح رسمی داخل خود RFC نیست؛ اگر بخواهید طرح، باید JSON Schema یا قرارداد OpenAPI را جدا اضافه کنید — و این متن فقط وقتی از آنها حرف میزند که واقعاً در پروژه باشند. برای فهرست کالا با فیلدهای تخت و تو در توی کم، JSON معمولاً پیادهسازی و خواندن کلاینت را کوتاهتر میکند.
معیار تصمیم، نه شعار: اگر سند را انسان با ساختار انتشاراتی ویرایش میکند، XML یا قالب سند دیگر را ارزیابی کنید. اگر برنامه شیء را از برنامه میگیرد، JSON مسیر کماصطکاک وب است. تبدیل بیفکر XML به JSON با از دست دادن ویژگیها و نامفضا، یک مهاجرت ناقص است نه مدرنسازی.
| نیاز | JSON معمولاً چه میدهد | XML معمولاً چه میدهد | یادداشت تصمیم |
|---|---|---|---|
| شیء و فهرست برای API وب | نحو کوتاه، parse بومی در JS | برچسب سنگینتر، DOM XML | برای ویترین و موبایل اغلب JSON |
| نامفضا و سند مختلط | ندارد | دارد | سند سازمانی / انتشارات |
| طرح و اعتبارسنجی | بیرون از RFC (مثلاً Schema) | XSD و ابزار بالغ | هر دو نیاز به قرارداد جدا دارند |
| نظر انسانی داخل فایل | مجاز نیست | توضیح مجاز است | JSON را با /* */ نفرستید |
| دودویی خام | باید کدگذاری شود (مثلاً Base64) | گاهی enclosure / نوع جدا | هیچکدام فایل بزرگ را خوب نمیبلعند |
دام عدد: دقت، بزرگی، پیشصفر
گرامر RFC عدد را مبنای ده با جزء صحیح، کسری و نما میداند. Infinity و NaN مجاز نیستند. پیشصفر ممنوع است: 01 JSON معتبر نیست. پیادهسازیها مجازند روی بازه و دقت حد بگذارند.
جملهٔ همعملی مهم در بند ۶ این است: نرمافزار IEEE 754 binary64 (دقت مضاعف) فراگیر است؛ همعملی خوب وقتی است که بیش از این دقت یا بازه انتظار نداشته باشید. عددهایی مثل 1E400 یا π با رقم خیلی زیاد نشانهٔ مشکل بالقوهاند. وقتی چنین نرمافزاری به کار میرود، اعداد صحیح در بازهٔ [-(2**53)+1 ، (2**53)-1] دقیقاً توافق میشوند.
ترجمهٔ فروشگاه: شناسهٔ عددی بزرگتر از حدود نه کوادریلیون را بهصورت عدد JSON نفرستید. شمارهٔ سفارش، کد ملی، یا شناسهٔ برفدانهٔ ۶۴بیتی را رشته کنید. مبلغ پول را اگر به سنت/ریال صحیح است، بهتر است صحیح بفرستید یا رشتهٔ اعشاری با تعداد رقم قفلشده؛ float قیمت را بههم میزند. این محدودیت زبان است، نه سلیقهٔ تیم.
دام تاریخ: نوعی در دستور زبان نیست
MDN صریح است: JSON تاریخ را بومی نمایندگی نمیکند. Date در stringify معمولاً به رشتهٔ ISO تبدیل میشود، پس اطلاعات کاملاً از بین نمیرود، ولی طرف گیرنده باید بداند آن رشته تاریخ است. بدون توافق، یک کلاینت همان را متن ساده نشان میدهد و دیگری یک روز عقب میماند چون منطقهٔ زمانی را نخوانده.
قرارداد پیشنهادی عملی: همیشه UTC با قالب ISO-8601 کامل بفرستید، نام فیلد را createdAt بگذارید نه timestamp مبهم، و در مستند واحد و منطقه را بنویسید. «تاریخ فقط روز» را از «لحظهٔ دقیق» جدا کنید. اگر سرور تاریخ محلی انبار را میفرستد و اپ کاربر در منطقهٔ دیگر است، موجودی «امروز» غلط میشود.
تولد، سررسید فاکتور، و لحظهٔ پرداخت سه معنایند. JSON هر سه را میتواند رشته کند؛ تشخیص معنا کار قرارداد است، کار parse نیست.
دام یونیکد و رمزگذاری
بند ۸٫۱ RFC برای متن JSON که بین سامانههای خارج از یک زیستبوم بسته رد و بدل میشود UTF-8 را الزام میکند. مشخصات قدیمیتر UTF-8 را اجباری نکرده بودند؛ تجربه نشان داد فقط UTF-8 همعملی میسازد. مولد نباید علامت ترتیب بایت (BOM، U+FEFF) به ابتدای متن شبکهای اضافه کند. تجزیهگر مجاز است BOM را نادیده بگیرد بهجای خطا.
رشته میتواند هر نویسهٔ یونیکد را داشته باشد، جز آنهایی که باید escape شوند: گیومه، ممیز وارونه، و نویسههای کنترل U+0000 تا U+001F. escape بهشکل \uXXXX برای صفحهٔ چندزبانهٔ پایه ممکن است. نویسهٔ خارج از BMP با جفت surrogate کد میشود؛ مثال RFC برای کلید سل (U+1D11E) برابر \uD834\uDD1E است.
هشدار همعملی بند ۸٫۲: گرامر اجازه میدهد دنبالهای که نویسهٔ یونیکد معتبر نیست — مثل \uDEAD تنها — داخل رشته بیاید. رفتار گیرنده غیرقابلپیشبینی است: طول متفاوت یا حتی استثنای مرگبار. معمولاً از بریدن رشتهٔ UTF-16 بدون بررسی جفت surrogate میآید. برای فارسی و عربی مشکل رایجتر mojibake است: اگر کسی UTF-8 را با Windows-1256 بخواند، نام کالا خراب میشود. Content-Type را application/json؛ charset در ثبت IANA اثر روی گیرندهٔ منطبق ندارد — RFC میگوید پارامتر charset تعریف نشده و افزودنش روی گیرندهٔ منطبق بیاثر است. پس UTF-8 را در تولید و مصرف فرض کنید، نه در یک پارامتر تزئینی.
مقایسهٔ رشته: RFC میگوید پیادهسازیهایی که متن را به واحدهای کد یونیکد تبدیل میکنند و واحدبهواحد مقایسه میکنند همعملاند. مقایسه روی شکل escapeنشده ممکن است "a\\b" و "a\u005Cb" را نابرابر ببیند در حالی که یک رشتهاند.
امنیت تجزیه: eval نیست
بند ۱۲ RFC هشدار میدهد JSON از نظر نحو از جاوااسکریپت وام گرفته، بنابراین وسوسهٔ parse با eval وجود دارد. این ریسک امنیتی غیرقابلقبول است چون متن میتواند کد اجرایی همراه داده داشته باشد. همان ملاحظه برای هر زبان دیگری که JSON در نحو آن معتبر است. دو نویسه مثل جداکنندهٔ خط U+2028 در JSON مجازند و در جاوااسکریپت نه؛ حتی «تقریباً eval» هم کامل نیست.
قانون عملی: فقط تجزیهگر JSON استاندارد. ورودی کاربر را مستقیم به parse ندهید مگر اندازه و عمق را محدود کرده باشید — خود RFC به پیادهسازی اجازهٔ حد روی حجم، عمق تودرتویی، دقت عدد و طول رشته میدهد. JSON بزرگ تودرتو میتواند حافظه را پر کند؛ این حملهٔ «بمب» است، نه ویژگی قالب.
JSON در قرارداد API فروشگاه
بدنه بهتنهایی قرارداد نیست. برای موجودی بگویید id رشته است یا عدد، quantity صحیح است، updatedAt ISO است. اگر کلاینت true را به صورت رشته بفرستد، parse موفق و منطق میشکند — نوع را بعد از parse در دامنه چک کنید. تغییر نام فیلد بدون نسخه همان شکست قرارداد ۰۳۶ است. null جزء JSON است و undefined نیست؛ حذف کلید را با null در مستند جدا کنید. کد HTTP را با بدنهٔ خطا جایگزین نکنید.
چه چیزی را در JSON نگذارید
- راز و کلید؛ قالب متنی لاگ میشود.
- شناسهٔ صحیح بزرگتر از بازهٔ امن binary64.
- بایت خام تصویر یا فایل؛ لینک یا کدگذاری صریح با اندازهٔ حد.
- نظر و کامای پایانی برای «خوانایی»؛ مولد استاندارد را بشکنید.
- تاریخ محلی بدون منطقه؛ فردا در سفر کاربر میشکند.
اگر موردی از این فهرست در API فعلی هست، قبل از افزودن کلاینت موبایل درستش کنید. هزینهٔ یک رشتهکردن شناسه از هزینهٔ سه باگ موجودی کمتر است.
جمعبندی
JSON طبق RFC 8259 قالب متنی حداقلی برای شیء، آرایه، رشته، عدد، بولی و null است. وب آن را به خاطر parse بومی، گسترهٔ زبانها، و همنشینی با APIهای HTTP دوست دارد. XML را برای سند و بعضی تبادلهای سازمانی حفظ کنید. عدد، تاریخ و یونیکد را در قرارداد قفل کنید؛ دستور زبان بهتنهایی کافی نیست. parse را به eval نسپارید.
قدم بعدی کوچک: یک پاسخ واقعی API را کنار RFC بخوانید. اگر شناسهٔ بزرگ عدد است یا تاریخ بدون منطقه، همان را در مستند اصلاح کنید.
برای خودِ قرارداد ارتباط ۰۳۶، برای منبع و فعل ۰۳۷ را بخوانید. JSON فقط شکل بایتهای داخل بازنمایی است.
منابع و مراجع
- IETF RFC 8259 — The JavaScript Object Notation (JSON) Data Interchange Format: https://www.rfc-editor.org/rfc/rfc8259.html
- MDN Web Docs — Working with JSON: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/JSON
- MDN Web Docs — Glossary: JSON: https://developer.mozilla.org/en-US/docs/Glossary/JSON
- MDN Web Docs — JSON (JavaScript): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
اگر میخواهید بعد از قالب پیام، شکل منبع و فعل را انتخاب کنید، به REST برگردید؛ اگر هنوز معلوم نیست دو سامانه چرا حرف میزنند، به تعریف API برگردید.
Author
SE
Soheil Ebrahimpour is the founder of FutureForge. He works on product design, architecture, and getting custom software into production.
Related notes
If you are unsure about architecture or the build path, we can talk about the project.
Describe the problem and the constraints. If there is a fit, we will schedule a conversation.




