خطاهای JSON معمولاً پیچیده نیستند، اما یک علامت کوچک میتواند کل سند را غیرقابل Parse کند. کامای اضافه، کوتیشن بستهنشده، Backslash اشتباه، عدد نامعتبر یا ترکیب کردن Syntax جاوااسکریپت با JSON از رایجترین علتهایی هستند که API، فایل تنظیمات یا برنامه را متوقف میکنند. در این راهنما، رایجترین خطاهای JSON و روش رفع آنها را با نمونههای خراب و اصلاحشده بررسی میکنیم و یک روش مرحلهبهمرحله برای پیدا کردن علت واقعی پیامهای خطا ارائه میدهیم.
پاسخ سریع: خطاهای JSON را چگونه رفع کنیم؟
برای رفع خطای JSON، ابتدا متن را با یک Parser یا JSON Validator معتبر بررسی کنید، سپس خط گزارششده و یک یا دو خط قبل از آن را ببینید. تطابق آکولاد و براکت، کوتیشن دوتایی کلیدها و Stringها، کاماهای میان اعضا، Escapeهای Backslash و شکل Numberها را کنترل کنید. پس از هر اصلاح، کل سند را دوباره Validate کنید. معتبر شدن Syntax فقط یعنی متن قابل Parse است؛ نوع فیلدها و قواعد داده باید جداگانه با Schema یا Validation برنامه بررسی شوند.
چرا یک خطای کوچک کل JSON را خراب میکند؟
JSON یک قالب متنی با Grammar مشخص است. Parser باید بتواند هر نویسه را در جایگاه دقیق خود تفسیر کند. وقتی Parser داخل یک Object قرار دارد، انتظار دارد بعد از نام Property یک دونقطه، بعد از مقدار یک کاما یا آکولاد بسته و داخل Array یک مقدار یا براکت بسته ببیند. اگر نویسهای خارج از این انتظار ظاهر شود، Parser نمیتواند با اطمینان ادامه دهد.
به همین دلیل پیام خطا معمولاً جایی را نشان میدهد که Parser دیگر قادر به ادامه نبوده است، نه الزاماً جایی که اشتباه اصلی رخ داده. مثلاً کامای جاافتاده در انتهای خط ۴ ممکن است هنگام رسیدن به کلید خط ۵ گزارش شود.
۱. استفاده از کوتیشن تکی بهجای کوتیشن دوتایی
در JSON استاندارد، نام Propertyها و مقادیر String باید با کوتیشن دوتایی نوشته شوند. کوتیشن تکی ممکن است در JavaScript یا بعضی زبانها معتبر باشد، اما JSON نیست.
نمونه اشتباه
{
'name': 'Sara',
'role': 'admin'
}
نسخه درست
{
"name": "Sara",
"role": "admin"
}
تبدیل سراسری کوتیشن تکی به دوتایی همیشه امن نیست؛ زیرا ممکن است خود متن شامل Apostrophe باشد. بهتر است داده را با Serializer تولید کنید، نه با Replace ساده رشتهای.
۲. کلید بدون کوتیشن
Object literal جاوااسکریپت میتواند در بعضی شرایط کلید بدون کوتیشن داشته باشد، اما نام تمام Propertyها در JSON باید String و داخل کوتیشن دوتایی باشند.
{
name: "Sara",
age: 28
}
نسخه معتبر:
{
"name": "Sara",
"age": 28
}
۳. کامای اضافه در انتهای Object یا Array
Trailing comma یکی از پرتکرارترین خطاهاست؛ مخصوصاً زمانی که JSON دستی نوشته یا از کد JavaScript کپی شده باشد.
{
"id": 10,
"active": true,
}
[
"red",
"green",
]
در هر دو نمونه باید کامای آخر حذف شود. کاما فقط میان دو عضو قرار میگیرد، نه بعد از آخرین عضو.
۴. فراموش کردن کاما میان اعضا
{
"id": 10
"name": "Keyboard"
}
Parser معمولاً هنگام رسیدن به کوتیشن ابتدای name خطا میدهد، اما علت واقعی در خط قبل است. نسخه درست:
{
"id": 10,
"name": "Keyboard"
}
۵. دونقطه جاافتاده یا استفاده از علامت مساوی
میان کلید و مقدار باید دقیقاً یک Colon قرار بگیرد. علامت مساوی، پیکان یا Semicolon بخشی از Syntax JSON نیست.
{
"name" = "Sara",
"active" => true
}
نسخه درست:
{
"name": "Sara",
"active": true
}
۶. آکولاد یا براکت بستهنشده
در ساختارهای تودرتو، پیدا کردن جفت گمشده دشوارتر میشود. تورفتگی منظم کمک میکند سطح هر Object و Array مشخص باشد.
{
"user": {
"name": "Sara",
"roles": ["admin", "editor"]
}
در این نمونه Object داخلی بسته شده، اما Object ریشه آکولاد پایانی ندارد. Formatter یا Editor دارای Bracket Matching میتواند محل جفتها را بهتر نشان دهد.
۷. کوتیشن بستهنشده در String
{
"message": "Operation completed,
"success": true
}
Parser ممکن است خطا را در ابتدای خط بعد گزارش کند، زیرا هنوز تصور میکند داخل String قرار دارد. کوتیشن پایانی مقدار message باید قبل از کاما قرار بگیرد.
۸. Backslash و Escape نامعتبر
Backslash داخل String آغاز یک Escape sequence است. فقط Escapeهای تعریفشده مانند \"، \\، \n، \t و \uXXXX معتبرند.
مسیر ویندوزی اشتباه
{
"path": "C:\new\files\report.txt"
}
در این متن، بخشهای \n و \f بهعنوان Escape تفسیر میشوند. برای نمایش Backslash واقعی باید آن را Escape کرد:
{
"path": "C:\\new\\files\\report.txt"
}
Escape ناشناخته
{
"code": "A\qB"
}
\q Escape معتبر JSON نیست. اگر هدف نمایش Backslash و حرف q است، باید "A\\qB" نوشته شود.
۹. خط جدید واقعی داخل String
String نمیتواند مستقیماً روی چند خط شکسته شود. خط جدید باید به شکل \n ذخیره شود.
{
"text": "line one
line two"
}
نسخه درست:
{
"text": "line one\nline two"
}
۱۰. استفاده از true، false یا null با حروف اشتباه
Literalهای JSON به بزرگی و کوچکی حروف حساساند و فقط فرم lowercase معتبر است.
| نامعتبر | معتبر | توضیح |
|---|---|---|
True | true | Boolean صحیح |
FALSE | false | Boolean غلط |
None | null | مقدار تهی JSON |
NULL | null | حروف باید کوچک باشند |
۱۱. استفاده از undefined، NaN و Infinity
این مقدارها در JavaScript شناختهشدهاند، اما جزو انواع داده JSON نیستند.
{
"missing": undefined,
"result": NaN,
"limit": Infinity
}
راهحل به قرارداد داده بستگی دارد. برای نبود مقدار معمولاً null مناسب است. برای NaN یا Infinity میتوان مقدار را حذف کرد، به String تبدیل کرد یا قرارداد صریح دیگری تعریف کرد؛ اما نباید بدون تصمیم معنایی آنها را کورکورانه جایگزین کرد.
۱۲. فرمت نامعتبر Number
Number در JSON قواعد محدودتری نسبت به بعضی زبانها دارد. Leading zero، Hex، Octal، علامت مثبت ابتدایی، جداکننده هزارگان و عددی که با نقطه تمام شود مجاز نیستند.
| نامعتبر | علت | نمونه معتبر |
|---|---|---|
01 | Leading zero | 1 |
0xFF | Hex مجاز نیست | 255 یا "0xFF" |
+12 | علامت مثبت ابتدایی مجاز نیست | 12 |
12. | بعد از نقطه رقم لازم است | 12.0 |
.5 | قبل از نقطه رقم لازم است | 0.5 |
1,000 | جداکننده هزارگان مجاز نیست | 1000 |
اعداد نمایی مانند 6.02e23 معتبرند. بااینحال Parser مقصد ممکن است برای عددهای بسیار بزرگ محدودیت دقت یا بازه داشته باشد؛ معتبر بودن Syntax تضمین نمیکند مقدار بدون افت دقت در نوع عددی زبان مقصد قرار بگیرد.
۱۳. قرار دادن Comment داخل JSON
{
// application port
"port": 8080
}
JSON استاندارد Comment ندارد. بعضی Parserها حالت JSON5 یا تنظیم permissive ارائه میکنند، اما فایلی که در آن محیط پذیرفته میشود ممکن است در API یا Runtime دیگری شکست بخورد. برای توضیح داده، Property مستنداتی تعریف کنید یا توضیح را خارج از فایل نگه دارید.
۱۴. وجود متن اضافی قبل یا بعد از مقدار ریشه
Result:
{
"ok": true
}
کلمه Result: بخشی از JSON نیست. همچنین دو Object مستقل پشت سر هم یک سند JSON معمولی تشکیل نمیدهند:
{"id": 1}
{"id": 2}
برای چند مقدار، آنها را داخل Array قرار دهید یا از قالبهایی مانند NDJSON طبق قرارداد مشخص استفاده کنید.
۱۵. مخلوط کردن JSON با Object جاوااسکریپت
این دو شبیهاند، اما یکسان نیستند. Object جاوااسکریپت میتواند Function، undefined، Symbol، کلید محاسبهشده، Comment و بعضی Syntaxهای دیگر داشته باشد. خروجی قابل انتقال باید با JSON.stringify() تولید شود.
const user = {
name: "Sara",
createdAt: new Date(),
greet() { return "hello"; }
};
const jsonText = JSON.stringify(user);
Function در خروجی حذف میشود و Date معمولاً به String تبدیل میشود. این تغییرها باید هنگام طراحی قرارداد داده در نظر گرفته شوند.
۱۶. اشتباه در Unicode Escape
Escape یونیکد باید دقیقاً چهار رقم Hex بعد از \u داشته باشد.
{
"letter": "\u12G4"
}
حرف G رقم Hex نیست. همچنین بعضی نویسههای خارج از BMP با یک جفت surrogate نمایش داده میشوند. بهترین روش این است که Serializer استاندارد مدیریت Unicode را انجام دهد.
۱۷. نویسه کنترلنشده یا BOM و Encoding ناسازگار
گاهی متن از نظر ظاهری درست است، اما فایل شامل نویسه کنترل، Encoding اشتباه یا Byte Order Mark غیرمنتظره است. نشانههای رایج شامل نمایش علامت سؤال، حروف فارسی خراب یا خطا در اولین نویسه فایل است.
- فایل را با UTF-8 ذخیره کنید.
- Encoding اعلامشده در HTTP header را با محتوای واقعی هماهنگ کنید.
- داده باینری را مستقیماً داخل String قرار ندهید؛ از قرارداد مناسب مانند Base64 استفاده کنید.
- در صورت خطا در Position صفر، وجود BOM یا نویسه پنهان را بررسی کنید.
۱۸. کلیدهای تکراری در یک Object
{
"role": "user",
"role": "admin"
}
این متن ممکن است توسط بسیاری از Parserها از نظر Syntax پذیرفته شود، اما رفتار کلید تکراری قابل اتکا نیست؛ بعضی Parserها مقدار آخر را نگه میدارند، بعضی مقدار اول و برخی امکان گزارش خطا دارند. کلید تکراری یک مشکل معنایی و سازگاری است و باید پیش از مصرف حذف یا Reject شود.
۱۹. JSON معتبر است، اما نوع ریشه اشتباه است
یک String، Number، Boolean یا null میتواند مقدار JSON معتبر باشد:
"hello"
اما API ممکن است فقط Object را بپذیرد. بنابراین پیام «Expected object» الزاماً خطای Syntax نیست؛ ورودی Parse شده، ولی با قرارداد endpoint سازگار نیست.
۲۰. JSON معتبر است، اما Schema یا DTO ردش میکند
{
"email": 123,
"age": -20,
"roles": "admin"
}
این سند از نظر Syntax معتبر است، اما احتمالاً با مدل برنامه سازگار نیست. برای تشخیص این دسته، باید نوع فیلدها، Propertyهای لازم، Range، Pattern و قواعد Domain بررسی شوند.
| سطح خطا | مثال | راه تشخیص |
|---|---|---|
| Syntax | کامای اضافه یا کوتیشن باز | JSON Parser یا Validator |
| Schema | String بهجای Number | JSON Schema یا DTO Validation |
| Semantic | سن منفی یا تاریخ پایان قبل از شروع | قواعد Domain |
| Security | مقدار خطرناک در Query یا HTML | اعتبارسنجی Context و Encoding خروجی |
چگونه پیامهای رایج Parser را تفسیر کنیم؟
| پیام متداول | علتهای محتمل | اول چه چیزی را بررسی کنیم؟ |
|---|---|---|
| Unexpected token | نویسه غیرمنتظره، کوتیشن تکی، Comment یا متن اضافی | همان نویسه و خط قبل |
| Expected ',' or '}' | کامای جاافتاده یا Object ناقص | انتهای عضو قبلی |
| Unterminated string | کوتیشن پایانی جاافتاده یا خط جدید واقعی | شروع String و Escapeها |
| Invalid escape character | Backslash قبل از حرف نامعتبر | مسیرها و Regexهای ذخیرهشده |
| Extra data | متن یا مقدار دوم بعد از پایان JSON | بعد از آکولاد یا براکت نهایی |
| Maximum depth exceeded | ساختار بیشازحد تودرتو | عمق داده و محدودیت Parser |
روش مرحلهبهمرحله رفع خطای JSON
- نسخه خام را حفظ کنید. پیش از ویرایش یک کپی از ورودی داشته باشید تا اصلاحهای اشتباه قابل بازگشت باشند.
- با Parser واقعی Validate کنید. Regex یا بررسی چشمی برای سندهای بزرگ کافی نیست.
- خط و ستون را پیدا کنید. علاوه بر خط گزارششده، خط قبلی و شروع ساختار فعلی را ببینید.
- ساختار را کوچک کنید. بخشهای سالم را موقتاً حذف کنید تا کوچکترین نمونه خراب باقی بماند.
- کوتیشن، کاما و جفت براکت را کنترل کنید. بیشترین خطاها در همین سه گروهاند.
- Escape و Encoding را بررسی کنید. مخصوصاً در مسیر فایل، Regex، متن چندخطی و داده فارسی.
- پس از رفع Syntax، Schema را اجرا کنید. موفقیت Parse پایان Validation نیست.
- کل سند را دوباره تست کنید. اصلاح نخست ممکن است فقط اولین خطا را آشکار کرده باشد.
تکنیک نصفکردن برای JSONهای بزرگ
وقتی فایل هزاران خط دارد، بررسی دستی ناکارآمد است. اگر ساختار اجازه میدهد، نیمی از اعضای Array یا Propertyهای Object را موقتاً حذف کنید و دوباره Validate کنید. اگر خطا باقی ماند، مشکل در نیمه باقیمانده است؛ اگر رفع شد، مشکل در بخش حذفشده بوده است. با تکرار این روش، محدوده خطا سریع کوچک میشود.
این کار را روی نسخه کپی انجام دهید و مراقب باشید حذف بخشها خودش ساختار را خراب نکند. برای Array باید کاماهای مرزی و برای Object باید جفت کلید و مقدار کامل حذف شوند.
اعتبارسنجی و نمایش خطا در JavaScript
function parseJsonSafely(text) {
try {
return { ok: true, value: JSON.parse(text), error: null };
} catch (error) {
return {
ok: false,
value: null,
error: error instanceof Error ? error.message : "Invalid JSON"
};
}
}
برای برنامه واقعی، اندازه ورودی را محدود کنید و پیام خطا را با اطلاعات حساس ترکیب نکنید. بعضی Runtimeها Offset میدهند؛ میتوان Offset را به خط و ستون تبدیل کرد تا تجربه کاربر بهتر شود.
رفع خطا در Python
import json
try:
data = json.loads(text)
except json.JSONDecodeError as exc:
print(f"{exc.msg} at line {exc.lineno}, column {exc.colno}")
اطلاعات lineno، colno و pos برای یافتن محل تقریبی مفیدند. گزینههای غیر استاندارد Parser را فقط زمانی فعال کنید که فرمت ورودی عمداً JSON استاندارد نیست.
رفع خطا در C#
using System.Text.Json;
try
{
using JsonDocument document = JsonDocument.Parse(jsonText);
Console.WriteLine("Valid JSON");
}
catch (JsonException ex)
{
Console.WriteLine($"{ex.Message}");
Console.WriteLine($"Line: {ex.LineNumber}, Byte: {ex.BytePositionInLine}");
}
در ASP.NET Core ممکن است خطا پیش از ورود به Action و هنگام Model Binding رخ دهد. پاسخ خطای API باید قابل فهم باشد، اما جزئیات داخلی Stack Trace را در محیط Production افشا نکند.
چرا نباید JSON را با اتصال رشتهها بسازیم؟
const json = '{"name":"' + userInput + '"}';
اگر ورودی شامل کوتیشن، Backslash یا نویسه کنترل باشد، خروجی خراب میشود و در بعضی Contextها خطر امنیتی ایجاد میکند. بهجای آن Object بسازید و از Serializer استفاده کنید:
const json = JSON.stringify({ name: userInput });
Serializer Escapeها، Boolean، null، Array و Object را مطابق قواعد پیادهسازی مدیریت میکند. بااینحال باید بدانید انواع غیرقابل نمایش مانند Function یا چرخههای Object چه رفتاری دارند.
خطاهای JSON در درخواست API
گاهی بدنه درخواست صحیح است، اما API همچنان آن را JSON نامعتبر گزارش میکند. این موارد را بررسی کنید:
- Header مربوط به
Content-Typeبا فرمت بدنه هماهنگ باشد. - بدنه دوبار Stringify نشده باشد؛ یعنی بهجای Object، یک String شامل JSON ارسال نشده باشد.
- Encoding درخواست UTF-8 و بدون نویسه پنهان غیرمنتظره باشد.
- Proxy یا Middleware بدنه را تغییر نداده باشد.
- Payload ناقص نشده و محدودیت اندازه درخواست آن را قطع نکرده باشد.
- API علاوه بر Syntax، DTO یا Schema خاصی نخواهد.
نمونه Double Encoding
این مقدار یک Object JSON است:
{"name":"Sara"}
اما این مقدار یک String است که داخلش متن JSON قرار دارد:
"{\"name\":\"Sara\"}"
هر دو از نظر Syntax معتبرند، ولی معنای متفاوتی دارند. اگر Server انتظار Object داشته باشد، نمونه دوم رد میشود.
نکات امنیتی هنگام رفع خطا
- JSONهای حاوی Token، Password، Cookie یا اطلاعات شخصی را در ابزارهای ناشناس وارد نکنید.
- معتبر بودن JSON به معنی امن بودن مقدارها نیست؛ داده باید متناسب با محل استفاده Validate و Encode شود.
- برای ورودیهای بسیار بزرگ، محدودیت اندازه و عمق تعریف کنید تا مصرف CPU و حافظه کنترل شود.
- پیام خطای Production نباید Stack Trace، مسیر سرور یا ساختار داخلی مدل را افشا کند.
- کلید تکراری، عدد بسیار بزرگ و Unicode غیرعادی را طبق سیاست برنامه مدیریت کنید.
بهترین روشها برای جلوگیری از خطاهای JSON
- JSON را با Serializer استاندارد زبان تولید کنید.
- در Editor از Syntax highlighting و Bracket matching استفاده کنید.
- فایل را پیش از Commit یا Deploy با Parser Validate کنید.
- برای قرارداد API از JSON Schema یا DTO Validation بهره ببرید.
- تستهایی برای Payloadهای مرزی، null، Array خالی و Unicode بنویسید.
- در Pipeline، فایلهای JSON تنظیمات را بهصورت خودکار Parse کنید.
- فرمت استاندارد را با JSON5، Object literal یا YAML اشتباه نگیرید.
چکلیست سریع عیبیابی
- آیا تمام کلیدها داخل کوتیشن دوتاییاند؟
- آیا Stringها کوتیشن پایانی دارند؟
- آیا میان اعضا کاما وجود دارد و بعد از عضو آخر حذف شده است؟
- آیا تعداد آکولاد و براکت باز و بسته متعادل است؟
- آیا Backslashها بهدرستی Escape شدهاند؟
- آیا Numberها Leading zero، Hex یا Infinity ندارند؟
- آیا Literalها دقیقاً
true،falseوnullهستند؟ - آیا Comment یا متن اضافی وجود ندارد؟
- آیا فقط یک مقدار ریشه وجود دارد؟
- آیا پس از Parse، Schema و قواعد Domain نیز بررسی شدهاند؟
جمعبندی
بیشتر خطاهای JSON از چند قانون ساده ناشی میشوند: کوتیشن دوتایی، کامای صحیح، جفت بودن آکولاد و براکت، Escape درست و استفاده از انواع محدود JSON. بهترین روش رفع خطا این است که به پیام Parser تکیه کنید، خط قبل از محل گزارششده را نیز ببینید، سند را کوچک کنید و بعد از اصلاح Syntax سراغ Schema و منطق داده بروید. استفاده از Serializer بهجای ساخت دستی رشته، Validation خودکار و محدودیت منابع، هم خطاها را کمتر میکند و هم پردازش JSON را قابل اعتمادتر میسازد.