JSON، TOML، YAML یا CSON: انتخاب قالب پیکربندی
جمعبندی: فایلهای پیکربندی به کامنت، تاریخ و متن چندخطی نیاز دارند که JSON در آنها کم میآورد. JSON، TOML، YAML و CSON را مقایسه کنید و ببینید تبدیل همیشه چه چیزی را از دست میدهد.

جمعبندی: برای تبادل ماشینی از JSON استفاده کنید، و برای پیکربندی نگهداریشده توسط انسان بر اساس اکوسیستم TOML یا YAML انتخاب کنید (YAML برای Kubernetes و CI، TOML برای ساختارهای مسطح یا تاریخهای بومی)؛ فقط وقتی مطمئن نیستید خواننده از گویش پشتیبانی میکند به JSONC برگردید.
JSON برای ماشینهایی وجود دارد که داده مبادله میکنند؛ فایل پیکربندی را انسان برای انسان مینویسد. این دو را قاطی کنید و یک
config.jsonمیگیرید که کامنت نمیپذیرد و کسی جرئت هرس کردنش را ندارد.
۱. از دو نوع فایل متفاوت شروع کنید
تبادل داده و پیکربندی هدف یکسان ندارند، هرچند همان فرد غالباً هر دو را روی همان ماشین مینویسد.
| بُعد | تبادل داده | پیکربندی |
|---|---|---|
| چه کسی مینویسد | برنامهای که مقداری را سریالایز میکند | انسان، یا انسانی که خروجی تولیدشده را ویرایش میکند |
| چه کسی میخواند | برنامه شخص دیگر | برنامه خودتان |
| چه چیزی مهم است | ابهام صفر، اندازه، سرعت تجزیه | خوانایی، کامنت، diffهای قابل بازبینی |
| فرکانس تغییر | هر درخواست | گاهبهگاه، با بازبینی |
| هزینه اشتباه | یک پاسخ 500 | سرویسی که بالا نمیآید |
JSON در ستون چپ تقریباً بینقص است: دستور زبان حداقلی، پارسر در هر زبان، و نبود کامنت یعنی نبود مشکل «کامنت از مقدار فاصله گرفت». در ستون راست، سختگیریاش اصطکاک محض است: بدون کامنت، بدون ویرگول انتهایی، بدون تاریخ، و متن چندخطی باید با \n در یک خط فشرده شود.
۲. چهار مدعی و نحوشان
- JSON: تعریفشده توسط RFC 8259 و ECMA-404، دقیقاً با شش نوع مقدار: شیء، آرایه، رشته، عدد، بولی و
null. استاندارد عملی تبادل است و تنها قالبی که تصمیم انتخابی نمیخواهد. - TOML: ساخته Tom Preston-Werner، با v1.0.0 منتشرشده در ژانویه ۲۰۲۱. هدف اعلامشدهاش قالب پیکربندی حداقلی با معناشناسی بدیهی است که بدون ابهام به جدول هش نگاشت میشود.
Cargo.tomlوpyproject.tomlبهصورت پیشفرض از آن استفاده میکنند. - YAML: مشخصات کنونی 1.2.2 است. تورفتگی سلسلهمراتب را بیان میکند و از کامنت، anchor و اسناد چندگانه پشتیبانی میکند. مانیفستهای Kubernetes، GitHub Actions و Ansible همه به آن وابستهاند، به قیمت مشخصات بزرگ و تفاوتهای پیادهسازی.
- CSON: CoffeeScript Object Notation، که پیکربندی را با object literalهای CoffeeScript مینویسد.
config.csonدر Atom از آن استفاده میکرد. از کامنت، کلید بیگیومه و ویرگول انتهایی پشتیبانی میکند، اما اکوسیستمش هرگز از دنیای جاوااسکریپت بیرون نرفت.
۲.۱ مقایسه توانایی
| توانایی | JSON | TOML | YAML | CSON |
|---|---|---|---|---|
| کامنت | ✗ | ✓ # |
✓ # |
✓ # |
| ویرگول انتهایی | ✗ | ✓ (آرایهها، جدولهای درونخطی) | ✓ (مجموعههای flow) | ✓ |
| کلید بیگیومه | ✗ | ✓ | ✓ | ✓ |
| تاریخ-زمان بومی | ✗ (فقط رشته) | ✓ چهار نوع تاریخ-زمان | ✓ (تجزیه خودکار در ۱.۱) | ✗ |
| رشتههای چندخطی | ✗ (escapeهای \n) |
✓ """ و ''' |
✓ اسکالر بلوکی و folded | ✓ heredoc |
| بازه عدد صحیح | نامحدود در مشخصات، double در عمل | ۶۴ بیتی علامتدار، باید بدوناتلاف باشد | دقت دلخواه بهعلاوه .inf/.nan |
از جاوااسکریپت پیروی میکند |
| تودرتویی | آکولاد و براکت | جدولها، آرایه جدولها، کلیدهای نقطهای | تورفتگی | تورفتگی |
| حساس به تورفتگی | ✗ | ✗ | ✓ | ✓ |
null |
✓ | ✗ | ✓ | ✓ |
| پوشش ابزار | هر زبان | زبانهای جریان اصلی | هر زبان، پیادهسازیهای متفاوت | فقط جاوااسکریپت |
دو خانه شایسته یادداشت است. TOML null ندارد که رایجترین شکست هنگام تبدیل از JSON است. رفتار «تاریخ بومی» YAML یعنی پارسر ۱.۱ 2026-10-31 را خودکار به شیء تاریخ تبدیل میکند، پس نوع بین زبانها منحرف میشود.
۳. کامنت: تنها ضعف JSON
اول نتیجه: اگر انسان فایل را نگهداری میکند و باید توضیح دهد چرا یک مقدار چنین است، از JSON استاندارد استفاده نکنید.
چهار مسیر عملی وجود دارد، به ترتیب میزان تهاجمی بودن:
- به JSONC روی آورید، که JSON استاندارد بهعلاوه کامنت و ویرگول انتهایی است.
settings.jsonوtsconfig.jsonدر VS Code از آن استفاده میکنند. هزینهاش این است که خواننده باید پارسر آگاه به کامنت مانندjsonc-parserاستفاده کند؛JSON.parseساده شکست میخورد. جزئیات در JSON5 و JSONC: JSON با کامنت. - یک سند جانبی نگه دارید.
config.jsonماشینخوان میماند، در حالی کهconfig.mdتوضیح میدهد هر فیلد چه معنایی دارد و چرا آن مقدار را دارد. هر دو در همان پوشهاند و در همان کامیت تغییر میکنند. - توضیحات را در schema بگذارید. کلیدواژههای
descriptionو$commentدر JSON Schema میتوانند فیلدها را مستند کنند، اما schemaها بهندرت همراه پیکربندی زمان اجرا ارسال میشوند، پس کسی که پیکربندی را میخواند ممکن است هرگز آنها را نبیند. - به TOML یا YAML بروید، و بگذارید خود قالب کامنتی فراهم کند که هر پارسری میفهمد.
{
// Fixed at 8080: the frontend build script reads this port for its proxy
"port": 8080,
// Disable watching to avoid exhausting inodes in CI
"watch": false
}
JSONC همچنان یک گویش است: پسوند .json میماند، اما فقط برخی ابزارها آن را میفهمند. وقتی داده از تیم خارج میشود یا از مرز سرویس عبور میکند، مرز بین JSONC و JSON استاندارد باید مستند شود.
۴. تاریخها و رشتههای چندخطی: زمین خانگی TOML
TOML تاریخ-زمان را به نوع کلاس اول با چهار گونه ارتقا میدهد: تاریخ-زمان دارای offset، تاریخ-زمان محلی، تاریخ محلی و زمان محلی. رشتههای چندخطی نحو اختصاصی دارند که شکست خط را حفظ میکند:
title = "json-toolkit"
created = 2026-10-31T09:00:00+08:00
description = """
A JSON toolkit for developers.
Every operation runs locally in the browser.
"""
همان اطلاعات در JSON باید تاریخ را به رشته تنزل دهد و شکست خطوط را escape کند:
{
"title": "json-toolkit",
"created": "2026-10-31T09:00:00+08:00",
"description": "A JSON toolkit for developers.\nEvery operation runs locally in the browser."
}
در JSON، "created" فقط رشتهای است که تصادفاً شبیه تاریخ است، پس اطلاعات نوع باید در قرارداد فیلد زندگی کند: هر دو طرف باید توافق کنند که فیلد همیشه RFC 3339 است. TOML به پارسر شیء تاریخ واقعی میدهد بدون نیاز به توافق شفاهی.
YAML هم میتواند متن چندخطی نگه دارد، اما دو سبک بلوکی معنای متفاوت دارند: | شکست خط را حفظ میکند در حالی که > آنها را به فاصله تا میزند. اشتباه انتخاب کنید و یک آدرس یا دستور SQL در یک خط فشرده میشود، خطایی که در بازبینی بسیار سخت گرفته میشود.
۵. عددها: نادیدهگرفتهشدهترین تفاوت
مشخصات JSON هیچ محدودیتی برای دقت عددی نمیگذارد، اما RFC 8259 هم هشدار میدهد که همکنشپذیری وقتی عددها بهعنوان double در IEEE 754 رفتار شوند امنترین است. در جاوااسکریپت، عددهای صحیح بالاتر از 2^53 - 1 بیصدا دقت را از دست میدهند:
JSON.parse('{"id":9007199254740993}').id
// 9007199254740992: the last digit is gone
TOML الزام میکند عددهای صحیح ۶۴ بیتی علامتدار بدوناتلاف مدیریت شوند و بهجای برش بیصدا خطا بدهند؛ شناورها از binary64 پیروی میکنند و ممکن است inf یا nan باشند. YAML 1.1 باری قدیمیتر حمل میکند: 1:30 بهعنوان ۹۰ (شصتگانی) تجزیه میشود و بولیها yes، no، on و off میپذیرند. از این رو «مشکل نروژ» کلاسیک که کد کشور NO به false تبدیل میشود.
برای پول، هرگز به شناور در هیچیک از این قالبها تکیه نکنید: از واحد خرد عدد صحیح، رشته یا نوع decimal پایگاهداده استفاده کنید. قالببندی و دقت با عمق بیشتر در مرزهای تبدیل JSON، YAML و XML پوشش داده شده است.
۶. جدولها و تودرتویی: مرزهای سخت TOML
TOML تودرتویی را با جدولها و آرایه جدولها بیان میکند:
[server]
port = 8080
[[routes]]
path = "/parse"
method = "POST"
[[routes]]
path = "/minify"
method = "POST"
دو مرز سخت دارد که پیش از تبدیل باید بدانید:
- ریشه سند TOML یک جدول است، پس سند JSONی که سطح بالایش آرایه است (مانند
[1, 2, 3]) نمایش TOML قانونی ندارد؛ باید بهصورت{"items": [...]}پیچیده شود؛ - TOML
nullندارد، پس فیلدnullدر JSON باید یا حذف شود یا با رشته خالی یا مقدار نگهبان جایگزین شود، با معناشناسی که به مصرفکننده سپرده میشود.
YAML برعکس است: عمق تودرتویی نامحدود است و anchorها بهعلاوه کلیدهای ادغام میتوانند قطعهها را بازاستفاده کنند:
defaults: &defaults
retries: 3
timeoutMs: 5000
server:
<<: *defaults
port: 8080
anchorها توانایی مخصوص YAML و ضرر تضمینی هنگام تبدیلاند: JSON نحو ارجاع ندارد، پس فایل گستردهشده رشد میکند و هیچ چیز ثبت نمیکند که دو بخش قبلاً پیکربندی یکسان بودند.
۷. انتخاب بر اساس سناریو
| سناریو | توصیه | دلیل |
|---|---|---|
| APIهای عمومی، صفهای پیام، کش | JSON | حداکثر همهجاگیری، هزینه مذاکره صفر |
| پیکربندی برنامه، مسطح و نوعدار | TOML | کامنت، تاریخ، عدد صحیح بدوناتلاف، رفتار پایدار پارسر |
| Kubernetes، CI، Ansible | YAML | اکوسیستم قفل شده است؛ تغییر قالب یعنی تغییر ابزار |
VS Code، tsconfig.json |
JSONC | بومی پشتیبانیشده، قالب جدیدی برای معرفی نیست |
| بازاستفاده از قطعههای پیکربندی | YAML | anchorها و کلیدهای ادغام تنها گزینه آمادهاند |
| تولیدشده و فقط ماشینی | JSON (فشرده) | کامنت لازم ندارد، بهترین اندازه و هزینه تجزیه |
| پروژههای قدیمی Atom یا CoffeeScript | CSON، اما مهاجرت را برنامهریزی کنید | اکوسیستم حاشیهای است و هزینه مهاجرت با زمان رشد میکند |
یک قاعده سرانگشتی: بگذارید اکوسیستم قالب پیکربندی را انتخاب کند، نه سلیقه شخصی. نوشتن Rust یعنی Cargo.toml، استقرار در Kubernetes یعنی YAML و ساخت افزونه VS Code یعنی JSONC. فقط در پروژه جدیدی بدون قید اکوسیستمی، «کدام نوشتنش دلپذیرتر است» پرسش واقعی است.
۸. مرزهای تبدیل
| جهت | اطلاعاتی که همیشه از دست میرود | توصیه |
|---|---|---|
| JSON → TOML | null، آرایههای سطح بالا، کلیدهای غیرقابل بیان |
اول ساختار را نرمال و فیلدهای خالی را حذف کنید |
| TOML → JSON | کامنتها، نوع تاریخ، inf / nan |
تاریخها را به رشته RFC 3339 تبدیل کنید |
| YAML → JSON | کامنتها، anchorها و کلیدهای ادغام، tagها، اسناد چندگانه | اول anchorها را گسترش دهید، سپس سند به سند تبدیل کنید |
| JSON → YAML | ضرر ساختاری ندارد، اما رشتههای تاریخ ممکن است خودکار تجزیه شوند | رشتههای تاریخ را گیومه بگذارید |
| CSON → JSON | کامنتها، عبارتهای CoffeeScript | یک بار مهاجرت کنید؛ دوطرفه همگام نکنید |
ابزارهای تبدیل مقدار را تضمین میکنند، هرگز کامنت را. پس خط لوله دوطرفهای طراحی نکنید که «JSON منبع است و YAML خروجی ساخت». یا یکطرفه تولید کنید، یا یک فایل منبع واحد نگه دارید.
۹. چکلیست
- [ ] مستند کنید کدام نوع فایل از کدام قالب استفاده میکند و گویشهای مجاز را فهرست کنید؛
- [ ] برای پیکربندی نگهداریشده توسط انسان TOML یا YAML و برای تبادل ماشینی JSON را ترجیح دهید؛
- [ ] تاریخها را در JSON بهصورت رشته RFC 3339 ذخیره و قالب را در schema علامت بزنید؛
- [ ] پول و عددهای صحیح بالاتر از
2^53را بهصورت رشته یا واحد خرد نمایش دهید، هرگز شناور؛ - [ ] هر قالب را در CI با پارسر خودش اعتبارسنجی کنید، هرگز با
JSON.parseبرای YAML؛ - [ ] قالبها را فقط یکطرفه مهاجرت دهید و فایل قدیمی را حذف کنید تا دو نسخه منحرف نشوند.
پرسشهای متداول
چرا تبدیل JSON به TOML روی برخی فیلدها شکست میخورد؟
TOML null ندارد و ریشه سند TOML یک جدول است، پس فیلد null در JSON باید حذف یا با رشته خالی یا نگهبان جایگزین شود، و آرایه سطح بالا باید بهصورت {"items": [...]} پیچیده شود. کامنتها، نوعهای تاریخ و inf/nan هنگام رفتن در جهت مخالف هم از دست میروند، و همین دلیل یکطرفه بودن تبدیل است.
آیا باید دو فایل پیکربندی در قالبهای مختلف نگه دارم؟
نه. ابزارهای تبدیل مقدار را تضمین میکنند اما هرگز کامنت را، پس خط لولهای که «JSON منبع است و YAML خروجی ساخت» منحرف میشود. یا یکطرفه تولید کنید، یا یک فایل منبع واحد نگه دارید و پس از مهاجرت فایل قدیمی را حذف کنید.
چگونه به فایل پیکربندی JSON کامنت اضافه کنم؟
JSON استاندارد کامنت ندارد. میتوانید به JSONC (گویش VS Code، خواندهشده با jsonc-parser) روی آورید، سند جانبیای توضیحدهنده هر فیلد نگه دارید، یا به TOML یا YAML بروید. فایلهایی که به سیستمهای دیگر میروند باید JSON استاندارد بمانند، با توضیحات در مستندات یا schema.
TOML یا YAML برای پیکربندی برنامه بهتر است؟
وقتی ساختار مسطح است، عمدتاً جفتهای کلید-مقدار، و تاریخ بومی مهم است TOML را انتخاب کنید؛ معناشناسیاش قابل پیشبینیتر و تفاوت پارسرها کوچکتر است. وقتی به تودرتویی عمیق، اسناد چندگانه، بازاستفاده anchor یا اکوسیستم هدف YAML-اول مانند Kubernetes یا CI نیاز دارید YAML را انتخاب کنید. هر دو کامنت را پشتیبانی میکنند، پس تفاوت واقعی پیچیدگی ساختاری و قفل اکوسیستمی است.
چرا NO در YAML به false تبدیل میشود؟
YAML 1.1 yes، no، on، off، y و n را بولی میداند، پس کد کشور NO نروژ بهعنوان false تجزیه میشود. این همان «مشکل نروژ» است. با استفاده از پیادهسازیای که از YAML 1.2 پیروی میکند، یا با گیومه گذاشتن هر رشتهای که ممکن است اشتباه تفسیر شود، از آن پرهیز کنید.
آیا CSON همچنان ارزش استفاده دارد؟
برای پروژههای جدید نه. CSON به اکوسیستم CoffeeScript وابسته است، ابزارهای نگهداریشده کمی دارد و پشتیبانی ویرایشگر و CI محدود است؛ پس از توقف نگهداری Atom موارد استفادهاش بیشتر کوچک شد. اگر پروژهای از قبل پیکربندی CSON دارد، یک مهاجرت یکباره به JSON، TOML یا YAML را برنامهریزی کنید نه اینکه بیشترش را اضافه کنید.