JSON
13 tools
JSON چیست؟
JSON (JavaScript Object Notation) یک فرمت سبکوزن و متنمحور برای تبادل داده است که خواندن و نوشتن آن برای انسان آسان، و تجزیه و تولید آن برای ماشین راحت است. این فرمت در اصل از JavaScript گرفته شده، اما مستقل از زبان است و اکنون استاندارد واقعی تبادل داده در وب بهشمار میرود.
JSON داده را بهصورت جفت کلید-مقدار سازمانیافته در آبجکتها و آرایهها نمایش میدهد. سادگی آن باعث شده که فرمت غالب برای REST APIها، فایلهای پیکربندی و ذخیره داده شود — و در بیشتر برنامههای مدرن جای XML پرحجمتر را بگیرد.
تاریخچهای کوتاه
JSON در اوایل دهه ۲۰۰۰ توسط Douglas Crockford رسمی شد، هرچند این فرمت پیش از آن ضمنی در نحو JavaScript وجود داشت. مشخصات آن در سال ۲۰۰۱ در json.org منتشر شد. RFC 4627 در سال ۲۰۰۶ دنبال شد و استاندارد فعلی ECMA-404 در سال ۲۰۱۳ منتشر گردید.
پیش از JSON، XML فرمت غالب تبادل داده در وب بود. سادگی JSON — بدون ویژگی، دستورالعمل پردازش یا فضای نام — باعث شد که فوراً در میان توسعهدهندگانی که برنامههای AJAX میساختند، محبوب شود. تا سال ۲۰۱۰، JSON بهطور عمده XML را از Web APIها کنار زده بود.
انواع داده در JSON
JSON دقیقاً از شش نوع داده پشتیبانی میکند. هر مقدار در یک سند JSON معتبر باید یکی از اینها باشد:
"hello world"هر توالی از کاراکترهای Unicode که در نقلقولهای دوتایی قرار گرفته باشد. دنبالههای فرار بکاسلش (\n، \t، \") پشتیبانی میشوند.
42 / 3.14 / 1e10عدد صحیح یا اعشاری. نمادگذاری علمی (1e10) مجاز است. در سطح JSON بین int و float تمایزی وجود ندارد.
true / falseتوکنهای تحتاللفظی true یا false (فقط حروف کوچک). truthy/falsy وجود ندارد — فقط بولین دقیق.
nullتوکن تحتاللفظی null (حروف کوچک). نمایانگر فقدان مقدار است. با undefined متفاوت است که یک نوع JSON نیست.
[1, "two", null]فهرستی مرتب از مقادیر که در کروشهها قرار گرفته. عناصر میتوانند از انواع مختلط باشند و آرایهها میتوانند بهصورت دلخواه تودرتو شوند.
{"key": "value"}مجموعهای نامرتب از جفتهای کلید-مقدار که در آکولادها قرار گرفته. کلیدها باید رشته باشند. مقادیر میتوانند هر نوع JSON باشند.
{
"string": "hello world",
"number": 42,
"float": 3.14,
"boolean": true,
"null": null,
"array": [1, 2, 3],
"object": { "nested": "value" }
}قوانین نحو JSON
JSON قوانین نحوی دقیقی دارد. یک انحراف کوچک باعث خطای تجزیه میشود. در اینجا شش قانون مهم برای بهخاطر سپردن آورده شده است:
تمام مقادیر رشتهای و کلیدهای آبجکت باید از نقلقولهای دوتایی استفاده کنند. نقلقولهای تکی در JSON معتبر نیستند. این رایجترین اشتباه برای توسعهدهندگانی است که از JavaScript میآیند.
JSON کاما انتهایی پس از آخرین عنصر آرایه یا آخرین ویژگی آبجکت را مجاز نمیداند. [1, 2, 3,] و {"a": 1,} هر دو نامعتبر هستند.
JSON نحو کامنت ندارد. // و /* */ معتبر نیستند. اگر در فایلهای پیکربندی به کامنت نیاز دارید، JSON5 یا YAML را در نظر بگیرید که هر دو از کامنت پشتیبانی میکنند.
JSON فقط از شش نوع اولیه پشتیبانی میکند. مقادیر JavaScript مانند undefined، NaN، Infinity و توابع قابل نمایش نیستند و در حین سریالسازی یا حذف میشوند یا به null تبدیل میگردند.
همه کلیدهای آبجکت باید رشتههای نقلقولگذاریشده باشند. کلیدهای عددی، شناسههای بدون نقلقول یا انواع دیگر مجاز نیستند. کلیدها باید منحصربهفرد باشند، هرچند بیشتر تجزیهکنندهها مقادیر تکراری را میپذیرند.
JSON حساس به حروف است. true، false و null باید همگی با حروف کوچک نوشته شوند. TRUE، False، NULL یا Null توکنهای نامعتبر هستند و باعث خطای تجزیه میشوند.
JSON نامعتبر در برابر معتبر
{
'name': 'Alice', // single quotes — invalid
age: 30, // unquoted key — invalid
"scores": [1, 2, 3,], // trailing comma — invalid
"note": undefined // undefined — invalid
}{
"name": "Alice",
"age": 30,
"scores": [1, 2, 3],
"note": null
}JSON در وب مدرن
REST APIها
JSON فرمت استاندارد بدنه برای درخواستها و پاسخهای REST API است. Content-Type: application/json رایجترین نوع MIME در وب مدرن است. تقریباً هر زبان برنامهنویسی دارای تجزیهکننده JSON داخلی است که همکاری بین سیستمها را یکپارچه میکند.
فایلهای پیکربندی
package.json، tsconfig.json، .eslintrc و بسیاری از ابزارهای توسعهدهنده دیگر از JSON برای پیکربندی استفاده میکنند. فرمت ساختاریافته و پشتیبانی جهانی از تجزیهکننده آن را کاربردی میکند، هرچند نبود کامنت انتقادی مداوم است.
پایگاههای داده NoSQL
پایگاههای داده سندی مانند MongoDB، CouchDB و Amazon DynamoDB داده را بهصورت اسناد JSON یا مشابه JSON ذخیره میکنند. این امکان ذخیرهسازی انعطافپذیر و بدون طرحواره را فراهم میکند که بهطور طبیعی با آبجکتهای برنامه تطابق دارد.
حالت و داده فرانتاند
localStorage و sessionStorage رشته ذخیره میکنند، بنابراین JSON.stringify/JSON.parse بهطور مداوم برای سریالسازی آبجکتهای JavaScript استفاده میشوند. پاسخهای API از fetch() بهصورت متن JSON میرسند و پیش از استفاده تجزیه میشوند.
JSON در برابر فرمتهای دیگر
JSON همیشه بهترین انتخاب نیست. در اینجا نحوه مقایسه آن با سایر فرمتهای داده رایج آمده است:
نحو سادهتر، حجم فایل کمتر، تجزیه آسانتر، خوانایی بیشتر برای توسعهدهندگان
پشتیبانی از ویژگیها، دستورالعملهای پردازش یا فضاهای نام XML ندارد
به متادیتای سند، مدلهای محتوای مختلط یا طرحوارههای XML (XSD/XSLT) نیاز دارید
نحو دقیقتر (ابهام کمتر)، پشتیبانی بهتر از ابزارها، قابلیت حمل بیشتر
پشتیبانی از کامنت ندارد، برای دادههای تودرتوی عمیق کمی پرحجمتر است
فایلهای پیکربندی قابل ویرایش توسط انسان، Docker Compose، GitHub Actions، مانیفستهای Kubernetes
پشتیبانی گستردهتر از اکوسیستم، تجزیه سریعتر، مدیریت نوع قابل پیشبینیتر
نوع تاریخ بومی ندارد، برای ساختارهای تودرتوی پیچیده کمتر انسانپسند است
Rust (Cargo.toml)، Python (pyproject.toml)، پیکربندی برنامه به سبک INI
داده ساختاریافته و تودرتو، نه محدود به سطرها و ستونهای صاف
حجم فایل بسیار بزرگتر، عملکرد ضعیفتر برای دادههای کاملاً جدولی
داده صفحهگسترده، خروجی پایگاه داده، دادهای که باید در Excel یا pandas باز شود
JSON Schema
JSON Schema یک واژگان برای اعتبارسنجی ساختار اسناد JSON است. یک طرحواره انواع مورد انتظار، فیلدهای اجباری و محدودیتها (minimum، maximum، pattern) یک مقدار JSON را توصیف میکند. نسخه فعلی JSON Schema 2020-12 است.
ابزارهایی مانند ajv (JavaScript)، jsonschema (Python) و اعتبارسنجهای داخلی در بسیاری از IDEها از JSON Schema پشتیبانی میکنند. OpenAPI (که قبلاً Swagger نام داشت) از JSON Schema برای توصیف بدنههای درخواست و پاسخ API استفاده میکند که آن را ستون فقرات مستندسازی مدرن API میسازد.
مشکلات رایج JSON
اعداد JSON بهصورت اعشاری با دقت مضاعف IEEE 754 تجزیه میشوند. اعداد صحیح بزرگتر از 2^53 دقت خود را از دست میدهند. IDهای بزرگ (Twitter snowflakeها، bigint پایگاه داده) را بهصورت رشته، نه عدد، پاس دهید.
JSON نوع تاریخ ندارد. تاریخها معمولاً بهصورت رشتههای ISO 8601 یا تایماستمپهای Unix سریالسازی میشوند. کد شما باید بداند از کدام قرارداد استفاده شده — هیچ راهی برای استنتاج آن از خود JSON وجود ندارد.
JSON.stringify روی مراجع دورانی آبجکت یک TypeError پرتاب میکند. باید چرخه را بشکنید یا از کتابخانهای که آن را مدیریت میکند استفاده کنید (json-stringify-safe، flatted).
JSON باید بهصورت UTF-8، UTF-16 یا UTF-32 رمزگذاری شود. UTF-8 استاندارد است. یک Byte Order Mark (BOM) در ابتدای فایل JSON از نظر فنی غیرمطابق است و برخی تجزیهکنندهها را خراب میکند.
هنگام تجزیه JSON غیرقابلاعتماد، ادغام آبجکتهای تجزیهشده در آبجکتهای موجود میتواند از طریق کلید __proto__ در معرض حملات آلودگی prototype قرار گیرد. همیشه JSON از منابع خارجی را اعتبارسنجی یا بهداشتی کنید.
{"key": null} و یک "key" گمشده از نظر معنایی متفاوت هستند. Null یعنی فیلد با مقدار غایب وجود دارد؛ گمشده یعنی فیلد مشخص نشده بود. JSON Schema میتواند هر دو تمایز را بیان کند.
سوالات متداول
JSON مخفف JavaScript Object Notation است. علیرغم این نام، JSON کاملاً مستقل از زبان است و در تقریباً هر زبان برنامهنویسی پشتیبانی میشود.
خیر. JSON یک فرمت متنی است که شبیه یک لیترال آبجکت JavaScript است، اما قوانین دقیقتری دارد: کلیدها باید دو نقلقولی باشند و از undefined، توابع یا کامنتها پشتیبانی نمیکند. یک سند JSON همیشه یک رشته است، نه یک آبجکت در حافظه.
خیر. مشخصات JSON نحو کامنت را شامل نمیشود. اگر کامنتهای // یا /* */ اضافه کنید، فایل شما دیگر JSON معتبر نیست. برای فایلهای پیکربندی که نیاز به کامنت دارند، JSONC، JSON5 یا YAML را در نظر بگیرید.
JSONP (JSON with Padding) یک راهحل برای سیاست same-origin مرورگر بود که JSON را در یک فراخوانی تابع پیچیده میکرد. این روش منسوخ شده — به جای آن از CORS استفاده کنید. مرورگرهای مدرن بهطور کامل از Cross-Origin Resource Sharing پشتیبانی میکنند.
در JavaScript: JSON.stringify(data, null, 2) تورفتگی ۲ فاصله اضافه میکند. در Python: json.dumps(data, indent=2). در ترمینال: cat file.json | python3 -m json.tool یا cat file.json | jq .
NDJSON (Newline Delimited JSON) یک آبجکت JSON در هر سطر ذخیره میکند. هر سطر میتواند بهطور مستقل تجزیه شود که امکان پردازش جریانی را فراهم میکند. برای فایلهای لاگ، جریانهای رویداد و خروجیهای داده بزرگ محبوب است.
فضای سفید بین توکنها بیمعنی است. {"a":1} و { "a" : 1 } یکسان هستند. قالببندی یک مسئله سبک و خوانایی است، نه معناشناسی.
مشخصات JSON هیچ محدودیت اندازهای تعیین نمیکند. در عمل شما محدود به حافظه تجزیهکننده و انتقال شبکه هستید. بیشتر فریمورکهای HTTP محدودیتهای پیشفرض اندازه بدنه را اعمال میکنند (۱ تا ۱۰ مگابایت). برای دادههای بزرگ، تجزیهکنندههای جریانی یا فرمتهای باینری مانند MessagePack را در نظر بگیرید.
مستقیماً نه. JSON یک فرمت متنی است. داده باینری (تصاویر، فایلها) باید قبل از جاسازی در JSON بهصورت Base64 رمزگذاری شوند که اندازه را حدود ۳۳٪ افزایش میدهد. برای دادههای سنگین باینری، multipart/form-data یا فرمتهای باینری مانند CBOR را در نظر بگیرید.
JSON5 یک فراستژه JSON است که اضافه میکند: کلیدهای بدون نقلقول، رشتههای تک نقلقولی، کاماهای انتهایی، کامنتها و رشتههای چندسطری. نوشتن آن برای انسان آسانتر است اما به یک تجزیهکننده جداگانه نیاز دارد. در پیکربندی Babel و برخی ابزارهای build استفاده میشود.