JSON Toolkit

JSON5 و JSONC: JSON با کامنت

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

مقدماتیحدود 10 دقیقه مطالعهانتشار 2026-10-30به‌روزرسانی 2026-10-30
تصویر جلد JSON5 و JSONC، JSON با کامنت

جمع‌بندی: برای کامنت در پیکربندی VS Code و TypeScript از JSONC استفاده کنید، وقتی به نحو گسترده‌تر literal در ES5.1 مانند تک‌گیومه یا کلید بی‌گیومه نیاز دارید از JSON5، و APIهای عمومی را روی JSON استاندارد نگه دارید.

JSON استاندارد کامنت را مجاز نمی‌داند، پس هر تیمی بی‌صدا می‌نویسدشان — تا روزی که ساخت می‌شکند. به‌جای پنهانی انجام دادن، گویش درستی انتخاب کنید.

۱. دو گویش انگیزه‌های متفاوت دارند

  • JSONC (JSON با Comments): JSON استاندارد به‌علاوه کامنت و ویرگول انتهایی، با تقریباً هیچ تغییر نحوی دیگر. استاندارد عملی اکوسیستم VS Code است — settings.json، tsconfig.json و .eslintrc.json همه از آن استفاده می‌کنند.
  • JSON5: بسیار جاه‌طلب‌تر، مستقیماً هم‌تراز با object literal ES5.1 — تک‌گیومه، کلید بی‌گیومه، هگزادسیمال، Infinity/NaN، ادامه خط با backslash و علامت + ابتدایی.

یک جمله برای تشخیصشان: JSONC فقط نوشتن را راحت می‌کند؛ JSON5 اجازه می‌دهد فایل پیکربندی را مثل جاوااسکریپت بنویسید.

۲. جدول مقایسه نحو

ویژگی JSON استاندارد JSONC JSON5
کامنت // /* */ ✗ ✓ ✓
ویرگول انتهایی ✗ ✓ ✓
رشته‌های تک‌گیومه ✗ ✗ ✓
کلیدهای بی‌گیومه ✗ ✗ ✓
عدد هگزادسیمال ✗ ✗ ✓
نقطه اعشار ابتدایی/انتهایی .5 5. ✗ ✗ ✓
عددهای شروع‌شده با + ✗ ✗ ✓
Infinity / NaN ✗ ✗ ✓
ادامه \ در پایان خط ✗ ✗ ✓
رشته‌های چندخطی ✗ ✗ ✓ (از طریق ادامه پیاده‌سازی می‌شود)
مقدار دلخواه در سطح بالا ✓ ✓ ✓

مشخصات کامل JSON5 تقریباً بیش از یک صفحه نیست؛ بسته json5 مدت‌ها توسط جامعه نگهداری شده و مرورگرها و Node یکسان رفتار می‌کنند.

۳. تجزیه: دو API، دو نوع توانایی موقعیت‌یابی

۳.۱ JSON5: تجزیه ساده کل سند

import JSON5 from 'json5';

const config = JSON5.parse(`
{
  // service port
  port: 8080,
  host: '0.0.0.0',
  features: ['json5', 'jsonc',],
  retries: 0x10,
}
`);

console.log(config.port, config.retries); // 8080 16

JSON5.parse یک شیء ساده بدون اطلاعات offset برمی‌گرداند — چون هدفش سناریوهای ویرایش نیست، فقط «خواندن پیکربندی».

۳.۲ JSONC: درخت نحوی با offset

ارزش jsonc-parser در تجزیه نیست، در ویرایش است. سه لایه API ارائه می‌دهد:

API هدف استفاده معمول
parse تجزیه به درختی حامل offset/length هایلایت نحوی، جمع‌شدن، پیمایش
visit پیمایش عمق-اول؛ callback مسیر گره را می‌گیرد بازرسی شبیه JSONPath
modify + applyEdits تولید ویرایش متنی حداقلی، سپس اعمال به متن اصلی تغییر یک مقدار با حفظ کامنت
import { parseTree, findNodeAtLocation, modify, applyEdits } from 'jsonc-parser';

const text = `{
  // port configuration
  "server": {
    "port": 8080 // 80 in production
  }
}`;

const tree = parseTree(text);
const portNode = findNodeAtLocation(tree!, ['server', 'port']);
console.log(portNode?.offset, portNode?.length);

const edits = modify(text, ['server', 'port'], 3000, {
  formattingOptions: { insertSpaces: true, tabSize: 2 },
});
console.log(applyEdits(text, edits));

خروجی کامنت‌های اصلی را نگه می‌دارد و فقط سه نویسه 8080 را جایگزین می‌کند:

{
  // port configuration
  "server": {
    "port": 3000 // 80 in production
  }
}

دقیقاً همان کاری که «ویرایش پیکربندی با عبارت باقاعده» نمی‌تواند: regex نمی‌داند کدام 8080 را تغییر دهد و نمی‌داند 8080 داخل رشته باید دست‌نخورده بماند.

۳.۳ پیام‌های خطا باید offset حمل کنند

کدهای خطای jsonc-parser مقادیر enum هستند؛ رایج‌ترین‌ها:

کد خطا معنا
InvalidSymbol نویسه‌ای ظاهر شد که نباید آنجا باشد
PropertyNameExpected نام کلید انتظار می‌رفت
ColonExpected دونقطه انتظار می‌رفت
CommaExpected ویرگول انتظار می‌رفت
CloseBraceExpected شیء بسته نشد
UnexpectedEndOfComment کامنت بسته نشد
InvalidEscapeCharacter escape نامعتبر

وقتی offset به خط و ستون تبدیل شود، ویرایشگر می‌تواند موج خطا را دقیقاً روی موقعیت خطادار بکشد.

۴. چه زمانی کدام

سناریو توصیه دلیل
بدنه درخواست/پاسخ API عمومی JSON استاندارد گویش‌ها توسط کلاینت‌های عمومی پشتیبانی نمی‌شوند
package.json، composer.json JSON استاندارد مدیران بسته فقط JSON استاندارد می‌فهمند
tsconfig.json، .vscode/settings.json JSONC پیش‌فرض اکوسیستم، بومی پشتیبانی‌شده توسط زنجیره ابزار
پیکربندی برنامه (کامنت لازم دارد) JSONC یا YAML کامنت باید حفظ شود در حالی که ابزارها همچنان می‌توانند بخوانند و بنویسند
نیاز به Infinity، هگزادسیمال، literalهای پیچیده JSON5 قوی‌ترین توان بیان
تبادل داده، لاگ، کش JSON خط‌محدود یا استاندارد جریان و همه‌جاگیری لازم است

قاعده سرانگشتی: اگر فایل توسط «ابزار غیرانسانی» خوانده می‌شود، JSON استاندارد را ترجیح دهید؛ گویش را فقط وقتی در نظر بگیرید که مطمئنید تنها کد خودتان می‌خواندش.

۵. سه نوع ریسکی که گویش‌ها وارد می‌کنند

۵.۱ سرریز نیاز

وقتی ابزاری دیگر فایل پیکربندی JSON5 را می‌خواند و JSON.parse صدا می‌زند، کاملاً از کار می‌افتد. نشانه معمول «محلی خوب کار می‌کند، روی Docker شکست می‌خورد» است — چون کانتینر مسیر خواندن متفاوتی اجرا می‌کند.

مقابله: به مخزن یک بررسی CI اضافه کنید که صریحاً فهرست کند کدام فایل‌ها مجاز به استفاده از گویش‌اند؛ بقیه به‌عنوان JSON استاندارد اعتبارسنجی می‌شوند.

۵.۲ غافلگیری‌های استنتاج نوع

JSON5 کلید بی‌گیومه و تک‌گیومه را مجاز می‌داند، اما اجازه نمی‌دهد ساختارهای literal مانند تاریخ یا عبارت باقاعده بیاورید — همچنان قالب داده است، نه ارزیابی جاوااسکریپت. مردم فرض کرده‌اند JSON5 می‌تواند new Date() را بیان کند و فقط شکست تجزیه دیده‌اند. JSON5 همان eval نیست.

۵.۳ حذف بی‌صدای کامنت‌ها

نه JSON5.stringify و نه JSON.stringify کامنت را حفظ نمی‌کنند. پس «بخوان، مقداری را تغییر بده، برگردان» همه کامنت‌ها را از دست می‌دهد. وقتی کامنت باید باقی بماند، تنها گزینه‌ها API ویرایش jsonc-parser یا کتابخانه YAML با پشتیبانی حفظ کامنت هستند.

۶. توصیه‌های عملی

  • [ ] جدول «نوع فایل → قالب» را در مستندات تیم نگه دارید تا کسی بداهه‌پردازی نکند؛
  • [ ] خواندن پیکربندی را در یک loadConfig() واحد بپیچید که در داخل تصمیم می‌گیرد از کدام پارسر استفاده کند، تا کد کسب‌وکار هرگز JSON.parse را مستقیم صدا نزند؛
  • [ ] هنگام تغییر برنامه‌ای پیکربندی دارای کامنت، از modify + applyEdits استفاده کنید؛ هرگز کل فایل را بازنویسی نکنید؛
  • [ ] فایل‌های گویش را در CI هم اعتبارسنجی کنید (jsonc-parser برای JSONC، JSON5.parse برای JSON5)، وگرنه خطاهای نحوی فقط در زمان اجرا ظاهر می‌شوند؛
  • [ ] برای رابط‌های عمومی، کلیدهای کش و payloadهای صف پیام از JSON استاندارد استفاده کنید.

پرسش‌های متداول

چگونه بین JSON5 و JSONC انتخاب کنم؟

بر اساس زمان اجرا انتخاب کنید نه تعداد نحو: VS Code، TypeScript و ESLint به‌صورت پیش‌فرض JSONC می‌خوانند، پس JSONC بهترین سازگاری را می‌دهد؛ تنها وقتی به نحو گسترده‌تر literal در ES5.1 نیاز دارید، مانند تک‌گیومه، کلید بی‌گیومه یا Infinity، به JSON5 بروید. هیچ کدام برای پاسخ API عمومی مناسب نیست.

چرا پارسر استاندارد JSON نمی‌تواند JSONC را مستقیم بخواند؟

JSONC کامنت و ویرگول انتهایی را مجاز می‌داند، در حالی که JSON.parse فقط JSON مطابق RFC 8259 می‌پذیرد و روی هر یک خطا می‌دهد. خواندن JSONC به پارسری مانند jsonc-parser نیاز دارد، یا حذف کامنت‌ها پیش از دادن متن به پارسر استاندارد.

آیا کامنت‌های JSONC باید پس از ویرایش فایل باقی بمانند؟

بله، اما فقط از طریق API ویرایش. modify و applyEdits در jsonc-parser گره هدف را تغییر می‌دهند در حالی که بقیه کامنت‌ها را حفظ می‌کنند؛ تجزیه به شیء و stringify کردن همه کامنت‌ها را حذف می‌کند.