جستوجوی پیام خطای JSON: از متن خطا مستقیم به رفع آن
جمعبندی: علت را با متن دقیق JSON.parse جستوجو کنید: ۱۲ خطای پرتکرار در Chrome، Firefox و Safari، شامل صفحههای خطای HTML، بریدگی و تجزیه دوباره.

جمعبندی: وقتی خطای JSON.parse ظاهر میشود، نخست موقعیت و توکن را بگیرید؛ موقعیت صفر یعنی پاسخ HTML، BOM یا نوع اشتباه را بررسی کنید، و پیام «Expected» یعنی کاراکتر قبلی را ببینید — از موقعیت گزارششده خطبهخط دوباره نخوانید.
متن خطا نویز نیست — پاسخ است. تجزیهکننده میگوید به کدام کاراکتر خورده، چه انتظاری داشته و واقعاً چه دیده است. جستوجو بر اساس پیام خطا بهتر از بازنویسی دستی کل سند است.
هر خطای JSON.parse() سه بخش دارد: موقعیت (افست کاراکتری یا خط/ستون)، انتظار (Expected...) و واقعیت (Unexpected token X یا xxx is not valid JSON). موتورها آن را متفاوت بیان میکنند — Chrome و Node (V8) میگویند Expected ',' or '}' after property value in JSON at position 25، Firefox میگوید JSON.parse: expected ',' or '}' after property value in object at line 3 column 1، Safari میگوید JSON Parse error: Expected ',' or '}' — اما هر سه به همان شکست نحوی اشاره میکنند. هنگام جستوجوی خطا، از عبارتبندی صرفنظر کنید و سه واقعیت را بگیرید: کدام کاراکتر، چه انتظاری، چه رسید.
۱. جدول جستوجوی ۱۲ خطا
ستون چپ، شناساییپذیرترین قطعه از کنسول شماست (عبارتبندی V8). گونههای Firefox/Safari در پرانتز آمدهاند.
| متن خطا (V8) | علت واقعی | رفع |
|---|---|---|
Unexpected token < in JSON at position 0 |
API بهجای JSON، HTML برگردانده است (صفحه ۴۰۴، قالب ۵۰۰، ریدایرکت ورود، بازگشت پروکسی) | نخست response.status و Content-Type را بررسی کنید؛ JSON را اصلاح نکنید |
Unexpected end of JSON input |
ورودی خالی یا بریده است: بدنه خالی، ۲۰۴، دانلود قطعشده، کپی بدون خط آخر | حالت خالی را مدیریت کنید، Content-Length را مقایسه کنید تا محل بریدگی را بیابید |
Unexpected token o / "[object Object]" is not valid JSON |
objectای که قبلاً تجزیه شده دوباره به JSON.parse() داده و به رشته تبدیل شده است |
typeof را بررسی کنید؛ اگر object است مستقیم استفاده کنید |
"undefined" is not valid JSON |
متغیر هرگز مقدار نگرفته است (JSON.parse(undefined)) |
مقدار پیشفرض اولیه بدهید؛ پیش از تجزیه محافظ بگذارید |
Expected double-quoted property name in JSON |
ویرگول انتهایی ({"a": 1,})؛ تجزیهکننده انتظار کلید دیگری دارد و } میبیند |
ویرگول پس از آخرین عضو را حذف کنید |
Expected property name or '}' in JSON |
کلید بدون گیومه یا با تکگیومه ({name: "Ada"}، {'name': 'Ada'}) |
هر کلید را در گیومه دوتایی بگذارید |
Expected ',' or '}' after property value in JSON |
ویرگول جاافتاده ({"a": 1 "b": 2}) یا کامنت پس از مقدار |
ویرگول را اضافه کنید؛ کامنت را حذف کنید |
Unexpected token '/' |
کامنت // یا /* */ درون JSON |
آن را حذف کنید یا پیکربندی را بهصورت JSONC تجزیه کنید |
Bad control character in string literal |
خط جدید خام، تب یا کاراکتر کنترلی U+0000–U+001F درون رشته | \n بنویسید؛ با JSON.stringify تولید کنید |
Unterminated string in JSON |
رشتهای با " باز شده و هرگز بسته نشده، یا گیومه داخلی escape نشده است |
گیومههای داخلی را بهصورت \" escape کنید |
Unexpected non-whitespace character after JSON |
دو سند در یک متن: {}{}، NDJSON، پوشش JSONP |
خطبهخط تقسیم و هر یک را تجزیه کنید، یا از تجزیهکننده NDJSON استفاده کنید |
JSON.parse is not a function |
متغیر خودتان نام سراسری JSON را سایه انداخته است |
متغیر را تغییر نام دهید؛ هرگز آن را JSON نام نگذارید |
دو مورد نخست سزاوار نگاهی نزدیکترند، چون هیچکدام معنایش «JSON شما اشتباه است» نیست — معنایش «آنچه دریافت کردهاید آن چیزی نیست که فکر میکنید».
۲. سه منبع رایج خطای موقعیت صفر
موقعیت صفر یعنی نخستین کاراکتر غیرمجاز است. اگر هیچ چیز مشکوک به نظر نمیرسد، احتمالاً کاراکتر نامرئی است. سه مظنون معمول:
نخست: <، یعنی HTML. این رایجترین خطای تجزیه در محیط عملیاتی است. URL اشتباه، نشستی که gateway آن را منقضی و ریدایرکت کرده، یا قالب خطای سرور — بدنه با <!DOCTYPE html> آغاز میشود و تجزیهکننده روی کاراکتر اول رها میکند. حرکت درست این است که پنل Network را باز کنید و پاسخ خام را بخوانید، سپس فراخوانی API را اصلاح کنید، نه JSON را.
دوم: BOM یا کاراکترهای عرضصفر. فایلهایی که Notepad ویندوز ذخیره میکند اغلب با BOM یوتیافهشت (\uFEFF) شروع میشوند و متنی که از صفحههای وب یا برنامههای چت کپی میشود ممکن است فاصله عرضصفر (\u200B–\u200D) داشته باشد. برای شما نامرئی، برای تجزیهکننده آشکار:
// Strip BOM and zero-width characters before parsing
const cleaned = raw.replace(/^\uFEFF/, '').replace(/[\u200B-\u200D]/g, '');
const data = JSON.parse(cleaned);
سوم: نوع اشتباه. JSON.parse(undefined) گزارش "undefined" is not valid JSON میدهد؛ JSON.parse(someObject) گزارش Unexpected token o میدهد (object به "[object Object]" تبدیل شده و o در موقعیت ۱ غیرمجاز است). هر دو یعنی «داده قبلاً تجزیه شده» یا «هرگز دادهای وجود نداشته». نوع را بررسی کنید، نه نحو را:
let data = text;
if (typeof data === 'string') {
data = JSON.parse(data); // Parse only when it really is a string
}
۳. موقعیت به پاییندست اشاره میکند؛ علت در بالادست است
دو خطا شما را درباره مکان گمراه میکنند و همان دو موردی هستند که در جدول بیش از همه بد خوانده میشوند:
- ویرگول جاافتاده:
{"a": 1 "b": 2}خطایExpected ',' or '}' after property valueرا در خط"b"گزارش میکند. گزارش درست است، اما رفع به انتهای خط قبلی تعلق دارد. - براکت بسته جاافتاده: تودرتویی عمیق که یک
}یا]کم دارد تجزیهکننده را وادار میکند همه چیز را تا انتهای ورودی ببلعد وUnexpected end of JSON inputگزارش کند. موقعیت انتهای فایل است؛ شکاف واقعی میتواند بسیار پیشتر باشد. به عقب بگردید و نزدیکترین{یا[بازنشده را بیابید — شمردن جفتها بهتر از چشمدواندن است.
تکنیک عمومی دونیمهسازی (bisection) است: متن پیش از موقعیت گزارششده را ببرید و تنها همان را تجزیه کنید. اگر تجزیه شد، مشکل نزدیک موقعیت گزارششده است؛ اگر نه، عقبتر دونیمه کنید. مرز نخستین قطعه شکستخورده محل واقعی خطاست. برای فایلهای بزرگ نخست سند را قالببندی کنید — با همترازی تورفتگی، سطح جاافتاده در یک نگاه دیده میشود (قالببند JSON آنلاین برای این کار خوب است).
۴. چهار «وضعیت سالمنمای» که درست تجزیه میشوند اما بد رفتار میکنند
بدتر از خطا، نبود خطا همراه با داده اشتباه است. در هر چهار مورد JSON معتبر است و تجزیهکننده راضی است — مشکل شکل داده است:
۱. رمزگذاری دوباره: کل سند دو بار JSON.stringify شده، پس تجزیه یک رشته به دست میدهد نه object. اگر typeof result === 'string' بود، دوباره تجزیه کنید — اما سریالسازی دوباره را در مبدأ بیابید و اصلاح کنید.
۲. کلید تکراری بیصدا بازنویسی میکند: {"name": "Tom", "name": "Jerry"} JSON معتبر است، بیشتر تجزیهکنندهها شکایت نمیکنند و مقدار دوم برنده میشود. این دام هنگام ادغام داده از چند منبع گزیده میشود؛ پیش از آنکه گزیده شوید با اعتبارسنج سختگیر JSON آشکارش کنید.
۳. NDJSON بهعنوان یک سند رفتار میشود: APIهای جریانی برای هر خط یک object بیرون میدهند؛ تجزیه کل متن با Unexpected non-whitespace character after JSON شکست میخورد. بر اساس \n تقسیم کنید و هر خط را جدا تجزیه کنید.
۴. از دست رفتن بیصدای دقت عدد: عددهای صحیح بزرگتر از 2^53 - 1 (شناسههای snowflake) با صفر شدن ارقام آخر برمیگردند، بدون هیچ خطایی. شناسهها را بهصورت رشته منتقل کنید.
رشته مشترک: تجزیهکننده باور دارد همه چیز خوب است. پس وقتی داده API اشتباه به نظر میرسد، نخست ۸۰ کاراکتر اول متن خام و typeof آن را چاپ کنید — پیش از بحث درباره محتوا، شکل را تأیید کنید.
۵. خطاها را در زمان نوشتن ناممکن کنید
جدول جستوجو ابزار پس از وقوع است؛ پیشگیری ابزار پیش از وقوع. چهار عادت بیشتر خطاها را پیش از رخ دادن میگیرند:
// 1. Two checks before parsing any response
const response = await fetch('/api/users');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: the API returned no data`);
}
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.includes('application/json')) {
throw new Error(`Expected JSON, got ${contentType}`);
}
const data = await response.json(); // 2. json() already parses — do not parse again
- برای تولید سریال کنید، هرگز به هم نچسبانید:
JSON.stringify()گیومهها، خطوط جدید و کاراکترهای کنترلی را درست مدیریت میکند؛ رشتههای دستساز منبع اصلیBad control characterوUnterminated stringهستند. - همیشه catch کنید: خطای پرتابشده
JSON.parseیک کرش همگام است مگر چیزی آن را بگیرد. برای ورودی غیرقابلاعتماد — localStorage، فایلهای بیرونی — بلوک catch به مقدار پیشفرض یا گزارش خطای صریح نیاز دارد. - ساختار را به Schema بسپارید: نحو معتبر به معنای ساختار معتبر نیست. فیلدهای غایب و انواع نادرست به اعتبارسنجی JSON Schema در مرز تعلق دارند؛ JSON Schema چه چیزی را حل میکند را ببینید.
۶. مسیر تصمیم سریع
کل مقاله را در یک ترتیب تصمیم فشرده کنید. وقتی خطایی میبینید، نخست موقعیت و توکن را بگیرید:
۱. موقعیت صفر → سه منبع را بررسی کنید: < (HTML)، BOM، نوع اشتباه؛
۲. end of input → بدنه خالی یا بریده را بررسی کنید، سپس به عقب برای براکتهای بازنشده بگردید؛
۳. Expected ... → کاراکتر قبلی را ببینید؛ معمولاً ویرگول یا گیومه جاافتاده است؛
۴. after JSON data → چند سند به هم چسبیدهاند؛ بر اساس خط تقسیم کنید؛
۵. درست تجزیه میشود اما داده اشتباه به نظر میرسد → چهار بررسی «سالمنما» را اجرا کنید.
همراه با تریاژ گامبهگام در چگونه خطاهای تجزیه JSON را رفع کنیم، ۹۰٪ مشکلات تجزیه در پنج دقیقه حل میشوند. خود متن خطا را نشانک کنید — همان گزارش اشکالزدایی است که تجزیهکننده برای شما نوشته، عبارتبندیاش هر سه سال یک بار عوض میشود و یک جستوجو هزینه یک سال را میدهد.
«Unexpected token in JSON» چه معنایی دارد؟
تجزیهکننده به کاراکتری خورده که در آن نقطه از دستور زبان JSON غیرمجاز است. توکن همان کاراکتر ردشده است: < معمولاً یعنی API HTML برگردانده، ' یعنی تکگیومه، / یعنی کامنت و یک حرف ساده معمولاً یعنی کلید بدون گیومه یا لیترال مخصوص JavaScript مانند undefined یا NaN. نخست توکن را بخوانید، سپس موقعیت را؛ علت به یکی محدود میشود.
چگونه «Unexpected end of JSON input» را رفع کنم؟
دو منبع: ورودی خالی (بدنه پاسخ خالی یا رشته خالی در localStorage) یا ورودی بریده (دانلود قطعشده، کپی بدون خط آخر، محدودیت اندازه). حالت خالی را با if (!text) return مدیریت کنید؛ سپس کامل بودن را بررسی و نزدیکترین {، [ یا " بازنشده را ببندید. توجه کنید خطا میتواند از براکت جاافتاده در عمق هم بیاید — موقعیت فقط تصادفاً انتهای فایل است.
چرا Chrome، Firefox و Safari خطاها را متفاوت گزارش میکنند؟
سه مرورگر موتورهای JS متفاوت (V8، SpiderMonkey، JavaScriptCore) دارند و هر یک خطاها را به شیوه خود بیان میکند؛ MDN همه گونههای رسمی را مستند میکند. اما هر سه خطا همان سه عنصر را حمل میکنند — موقعیت، انتظار، واقعیت — با معنای یکبهیک. آن را به عبارتبندی V8 ترجمه کنید و این جدول را همانطور استفاده کنید.
موقعیت خطا به جایی اشاره میکند که درست به نظر میرسد — حالا چه؟
خطای واقعی پیشتر است. موارد معمول: ویرگول جاافتاده (در خط بعدی گزارش میشود) و براکت بسته جاافتاده (در انتهای فایل گزارش میشود). از موقعیت گزارششده توکنبهتوکن عقب بروید، یا دونیمه کنید: نیمه اول را تنها تجزیه کنید و مرز نخستین قطعه شکستخورده محل واقعی خطاست.