JSON Toolkit

البحث عن رسائل خطأ JSON: من نص الخطأ مباشرة إلى الإصلاح

الخلاصة: ابحث عن السبب عبر رسالة JSON.parse الدقيقة: 12 خطأً شائعًا عبر Chrome وFirefox وSafari، بما في ذلك صفحات أخطاء HTML والاقتطاع والتحليل المزدوج.

متقدمقراءة نحو 8 دقيقةنُشر في 2026-10-30حُدِّث في 2026-11-04
غلاف جدول البحث عن رسائل خطأ JSON

الخلاصة: عندما يظهر خطأ JSON.parse، اقرأ الموضع والرمز أولًا؛ فالموضع 0 يعني فحص استجابة 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 '}' — لكن الثلاثة كلها تشير إلى الكسر النحوي نفسه. وعند البحث عن خطأ، تجاهل الصياغة والتقط الحقائق الثلاث: أي حرف، وما كان متوقعًا، وما وصل.

1. جدول البحث عن الأخطاء الـ12

العمود الأيسر هو الجزء الأكثر تميزًا في وحدة التحكم لديك (صياغة V8). وتظهر صيغ Firefox/Safari بين قوسين.

نص الخطأ (V8) السبب الحقيقي الإصلاح
Unexpected token < in JSON at position 0 أعادت API صفحة HTML (صفحة 404، قالب 500، إعادة توجيه تسجيل الدخول، احتياطي وسيط) لا JSON تحقق من response.status وContent-Type أولًا؛ لا تصلح JSON
Unexpected end of JSON input المُدخل فارغ أو مقتطع: جسم فارغ، 204، تنزيل منقطع، نسخ ناقص للسطر الأخير تعامل مع الحالة الفارغة، وقارن Content-Length لتحديد موضع القطع
Unexpected token o / "[object Object]" is not valid JSON كائن محلول مسبقًا أُعيد تمريره إلى JSON.parse() فحُوِّل إلى نص تحقق من typeof؛ فإن كان كائنًا استخدمه مباشرةً
"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 سطر جديد أو tab أو أي حرف تحكم آخر بين U+0000–U+001F داخل نص اكتب \n؛ وولِّد بـ JSON.stringify
Unterminated string in JSON نص فُتح بـ " ولم يُغلق، أو علامة اقتباس داخلية غير مهرَّبة اهرّب علامات الاقتباس الداخلية كـ \"
Unexpected non-whitespace character after JSON مستندان في نص واحد: {}{}، NDJSON، غلاف JSONP قسّم حسب الأسطر وحلّل كل سطر، أو استخدم محلل NDJSON
JSON.parse is not a function متغير خاص بك يحجب JSON العام أعد تسمية المتغير؛ ولا تسمّه JSON أبدًا

يستحق أول خطأين نظرة أقرب، لأن كليهما لا يعني "JSON لديك خطأ" — بل يعني "ما استلمته ليس ما تظنه".

2. ثلاثة مصادر شائعة لخطأ الموضع 0

الموضع 0 يعني أن الحرف الأول بالضبط غير صالح. وإن لم يبدُ شيء مريبًا، فالحرف على الأرجح غير مرئي. ثلاثة مشتبهين معتادين:

أولًا: <، أي HTML. هذا أكثر خطأ تحليل شيوعًا في الإنتاج. رابط خاطئ، أو جلسة منتهية أعادت توجيهها البوابة، أو قالب خطأ من الخادم — يبدأ الجسم بـ <!DOCTYPE html> ويتوقف المحلل عند الحرف الأول. الخطوة الصحيحة هي فتح لوحة Network وقراءة الاستجابة الخام، ثم إصلاح استدعاء API لا JSON.

ثانيًا: BOM أو أحرف بعرض صفري. كثيرًا ما تبدأ الملفات المحفوظة بـ Windows Notepad بـ BOM بترميز UTF-8 (\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]"، والحرف o غير صالح في الموضع 1). وكلاهما يعني "البيانات محلولة بالفعل" أو "لم تكن هناك بيانات أصلًا". افحص النوع لا الصياغة:

let data = text;
if (typeof data === 'string') {
  data = JSON.parse(data); // Parse only when it really is a string
}

3. الموضع يشير إلى ما بعده؛ والسبب قبله

هناك خطأان يضلّلانك بشأن الموقع، وهما أكثر مدخلَين يُسيء القراءة في الجدول:

  • فاصلة ناقصة: يُبلغ {"a": 1 "b": 2} بالرسالة Expected ',' or '}' after property value عند سطر "b". التقرير صحيح، لكن الإصلاح يقع في نهاية السطر السابق.
  • قوس إغلاق ناقص: يجعل تداخل عميق ناقص } واحدًا أو ] واحدة المحلل يبتلع كل شيء حتى نهاية المُدخل ويبلغ Unexpected end of JSON input. الموضع هو نهاية الملف؛ أما الثغرة الحقيقية فقد تكون بعيدًا إلى الوراء. ابحث للخلف عن آخر { أو [ غير مغلق — عدّ الأزواج أفضل من التخمين البصري.

التقنية العامة هي التنصيف: اقطع النص قبل الموضع المُبلَّغ عنه وحلّله منفردًا. فإن حلّ فالمشكلة قرب الموضع المُبلَّغ عنه؛ وإن لم يُحَلّ فنصّف أبعد إلى الوراء. وحدود أول جزء فاشل هي موضع الخطأ الحقيقي. في الملفات الكبيرة نسّق المستند أولًا — فبمحاذاة المسافات البادئة يصبح المستوى الناقص مرئيًا بلمحة (يعمل منسّق JSON على الإنترنت بشكل جيد لهذا الغرض).

4. أربع حالات "سليمة زائفة" تُحلَّل بلا خطأ لكنها تسيء التصرف

الأسوأ من خطأ أن لا يوجد خطأ والبيانات خاطئة. في الحالات الأربع كلها يكون JSON صالحًا ويكون المحلل راضيًا — والمشكلة في شكل البيانات:

  1. الترميز المزدوج: سُلِّل المستند كله بـ JSON.stringify مرتين، فينتج عن التحليل نص لا كائن. فإن كان typeof result === 'string' فحلّل مرة أخرى — لكن ابحث عن التسلسل المزدوج وأصلحه في المصدر.
  2. المفاتيح المكررة تُستبدل بصمت: {"name": "Tom", "name": "Jerry"} صالح في JSON، ومعظم المحللات لا تشكو، والقيمة الثانية هي الغالبة. وهذا يلسع عند دمج بيانات من عدة مصادر؛ فاكشفه بـ مدقق JSON صارم قبل أن يلسعك.
  3. NDJSON يُعامل كمستند واحد: تصدر API المتدفقة كائنًا لكل سطر؛ وفشل تحليل النص كله بالرسالة Unexpected non-whitespace character after JSON. قسّم على \n وحلّل كل سطر.
  4. فقدان دقة الأعداد بصمت: الأعداد الصحيحة فوق 2^53 - 1 (معرّفات snowflake) تعود بأرقام أخيرة أصفارًا، دون أي خطأ على الإطلاق. أرسل المعرّفات كنصوص.

الخيط المشترك: المحلل يعتقد أن كل شيء على ما يرام. لذا عندما تبدو بيانات API خاطئة، اطبع أول 80 حرفًا من النص الخام ونوعها typeof أولًا — تأكد من الشكل قبل مناقشة المحتوى.

5. اجعل الأخطاء مستحيلة عند الكتابة

جدول البحث أداة ما بعد الحدث؛ والوقاية أداة قبله. أربع عادات تعترض معظم الأخطاء قبل حدوثها:

// 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.
  • التقط دائمًا: خطأ JSON.parse المرمي هو انهيار متزامن ما لم يعترضه شيء. ومع المُدخل غير الموثوق — localStorage والملفات الخارجية — تحتاج كتلة catch إلى قيمة افتراضية أو تقرير خطأ صريح.
  • فوّض البنية إلى Schema: الصياغة الصالحة لا تعني البنية الصالحة. الحقول الناقصة والأنواع الخاطئة تنتمي إلى تحقق JSON Schema على الحدود؛ راجع ما يحلّه JSON Schema.

6. مسار القرار السريع

اضغط المقال كله في ترتيب قرار واحد. عندما ترى خطأً، التقط الموضع والرمز أولًا:

  1. الموضع 0 → افحص المصادر الثلاثة: < (HTML)، BOM، نوع خاطئ؛
  2. end of input → تحقق من جسم فارغ أو مقتطع، ثم ابحث للخلف عن أقواس غير مغلقة؛
  3. Expected ... → انظر إلى الحرف السابق؛ إنه عادةً فاصلة أو علامة اقتباس ناقصة؛
  4. after JSON data → سُلِّبت مستندات متعددة؛ اقسِم حسب السطر؛
  5. يُحلَّل بلا خطأ لكن البيانات تبدو خاطئة → شغّل فحوص "السليمة زائفة" الأربعة.

وبالاقتران مع الفرز التدريجي في كيفية إصلاح أخطاء تحليل JSON، تُحل 90% من مشكلات التحليل خلال خمس دقائق. احتفظ بنص الخطأ نفسه في المفضلة — فهو سجل التصحيح الذي كتبه لك المحلل، وتتغير صياغته مرة كل ثلاث سنوات، وعملية بحث واحدة تكفي لعام.

ماذا تعني رسالة "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 واستخدم هذا الجدول كما هو.

موضع الخطأ يشير إلى مكان يبدو سليمًا — ماذا الآن؟

الخطأ الحقيقي أبعد إلى الوراء. حالات نموذجية: فاصلة ناقصة (يُبلَّغ عنها في السطر التالي) وقوس إغلاق ناقص (يُبلَّغ عنه في نهاية الملف). امشِ للخلف من الموضع المُبلَّغ عنه رمزًا برمز، أو نصّف: حلّل النصف الأول منفردًا، فتكون حدود أول جزء فاشل هي موضع الخطأ الحقيقي.