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

الخطوة 1: التقط الإرسال الذي حدث فعلًا

افتح لوحة الشبكة قبل أن ترسل، واضبط السجل على الاحتفاظ بالمدخلات عبر التنقل، ثم نفّذ إرسالًا تجريبيًا غير ضار على حساب يُسمح لك باستخدامه. اختر الطلب الذي بدأه النموذج نفسه لا طلب مستند الصفحة.

احترس من عوامل التصفية. مرشح XHR أو Fetch مريح، لكن إن كان الإطار ما زال يرسل عبر إطار مخفي أو نموذج يُنشأ ديناميكيًا فإن التصفية ستخفي الطلب الوحيد المهم. أرسل أولًا بلا تصفية وانظر ما ظهر.

بالنسبة إلى الطلب الذي اخترته، سجّل ستة أمور قبل أن تفسّر أي شيء: الطريقة، والرابط الكامل مع سلسلة الاستعلام، والحالة، وسلسلة إعادة التوجيه، ونوع محتوى الاستجابة، والأسطر الأولى من الجسم. يغطي مرجع لوحة الشبكة في Chrome DevTools عرض الترويسات والاستجابة والمُبدئ التي تظهر فيها، وتعرض اللوحات المكافئة في المتصفحات الأخرى الحقول نفسها.

الخطوة 2: تأكد أن الطلب هو ما تظنه

عدد مفاجئ من أخطاء JSON هو في الحقيقة أخطاء توجيه. إذا رمت معالجة الإرسال استثناءً قبل أن تنادي preventDefault، نفّذ المتصفح إرسال POST أصليًا للنموذج إلى ما تقوله سمة action، وأجاب الخادم بصفحة HTML كاملة. المعالجة لا تعمل أبدًا، أي أن JSON لم يُطلب قط.

قارن الرابط في اللوحة بالرابط الذي يناديه JavaScript لديك. ابحث عن إعادة توجيه تنتهي في مكان آخر، أو شرطة أخيرة ناقصة أو زائدة، أو عدم تطابق في الطريقة حيث ترسل المعالجة GET ويقبل الطرف POST، أو نموذج يرسل إلى مسار نسبي من صفحة انتقلت. تابع سلسلة إعادة التوجيه حتى النهاية وسجّل الرابط النهائي لا الأول.

ثم افحص المُبدئ. إذا جاء الطلب من تنقل مستند لا من النص البرمجي، فقد وجدت المشكلة، ولن يفيد أي تغيير في محلّل الاستجابة.

الخطوة 3: صنّف النتيجة في أربع فئات

كل نتيجة تنتمي إلى واحدة فقط من هذه الفئات، والفئة تحدد أين تنظر بعد ذلك.

What you seeCategoryWhere to look
Request never finishes, TLS or connection errorNo usable responseEndpoint reachability, certificate, front-end timeout
Request completes, script gets an opaque failureAccess blockedCross-origin policy, credentials mode, missing response header
200 with an HTML body or a login formWrong representationRedirect, expired session, route fallback, error handler
Body begins with a notice then valid JSONWrong representationServer-side warning output before serialisation
Valid JSON, framework rejects itContract mismatchEnvelope shape, field names, value types

الصفوف الوسطى هي التي يُخطئ الناس في تشخيصها، لأن الحالة 200. صفحة تسجيل دخول تُبلَغ بعد إعادة توجيه هي استجابة HTTP سليمة تمامًا ومستند JSON سيئ للغاية. ونوع المحتوى application/json لا يصلح ذلك: إنه تسمية، والجسم الموسوم خطأً يظل يفشل في التحليل. أما «الوصول محجوب» فهو الصف الذي يبدو طلبًا مكتملًا: تعرض اللوحة حالة، لكن سياسة المصادر المتقاطعة تحجب الجسم، فهو بالنسبة إلى النص البرمجي المستدعي غير قابل للاستخدام كالمهلة تمامًا.

الصف الرابع شائع بالقدر نفسه على حزم PHP والأطر الأقدم. تحذير إهمال يُطبع قبل الحمولة المُرمَّزة ينتج جسمًا لا يقبله أي محلّل JSON، وغالبًا يكون التحذير هو التفسير كله.

الخطوة 4: اقرأ خطأ المحلّل حرفيًا

يسمّي نص الخطأ أول محرف كسر التحليل، وهذا يحدد الفئة عادةً بلا أي تخمين.

Error text (Chrome/V8)What it means
Unexpected token < in JSON at position 0The body starts with markup: an HTML page or an error document
Unexpected end of JSON inputEmpty body, or the response was truncated
Unexpected token o in JSON at position 1You parsed something already parsed, typically an object rather than text
Unexpected token uThe body starts with the bare word undefined, usually an empty response rendered as a string

الجسم الفارغ مع الحالة 200 حالة قائمة بذاتها: نُفّذ الطرف ولم ينتج شيئًا، وعالج شيء لاحق ذلك كنجاح. هذا عطل عقد في التطبيق لا عطل نقل، وموضعه الخطوة التالية لا الوسيط. يصوغ Firefox وSafari الأعطال الأربعة نفسها بصياغة مختلفة، فطابق على المحرف أو على الجسم الفارغ لا على النص الحرفي.

الخطوة 5: أصلح الطبقة التي تشير إليها الأدلة

في مشكلة التوجيه أصلح الطلب: صحّح action، وامنع المعالجة من السقوط، واجعل الطرف والطريقة متطابقين، ثم أعد الاختبار. وفي مشكلة التمثيل أصلح ما أنتج الجسم، واعرف لماذا يُعاد مستند خطأ حيث تُتوقع بيانات. وفي مشكلة العقد اقرأ البنية التي يتوقعها إطارك فعلًا في الإصدار الذي تشغله، وشكّل الاستجابة عليها بدلًا من إرخاء العميل.

الاستجابة المحجوبة تحتاج مرورًا خاصًا بها، لأن الطلب نفسه قد يكون صحيحًا وقد لا يصل الجسم إلى شفرتك أبدًا. قارن Access-Control-Allow-Origin في الاستجابة بـ Origin الدقيق الذي أرسله المتصفح، وتذكر أن الحرف البديل لا يلبي طلبًا يحمل بيانات اعتماد. اقرن credentials: 'include' عند العميل بـ Access-Control-Allow-Credentials: true عند الخادم، وافحص ما إذا كان النداء استخدم الوضع no-cors حيث يكون الجسم المعتم نتيجة موثقة لا عيبًا.

استبدال المحلّل بشيء متسامح هو الإصلاح الوحيد الذي يجب تجنبه. تقييم الاستجابة كشيفرة، أو تجريد النص حتى يُحلَّل، يخفي عدم تطابق العقد ويضيف سطح حقن مقابل الصمت. وبالمثل، فحص الحالة منفصلة عن الجسم مطلوب: استجابة 200 تحمل كائن خطأ على مستوى التطبيق أمر عادي في كثير من واجهات API ويجب معالجته بقراءة الحمولة.

عندما تحتاج مساعدة من غيرك، شارك سجلًا أدنى — الطريقة، والرابط، والحالة، والرابط النهائي بعد إعادات التوجيه، ونوع محتوى الاستجابة، وشكل الجسم، والعقد المتوقع — بدلًا من تصدير خام. تحوي أرشيفات الشبكة ملفات تعريف الارتباط والرموز وسلاسل الاستعلام والبيانات الشخصية التي كانت في النموذج، والمعقّم التلقائي ليس مراجعة.

  • التقط الطلب بلا تصفية قبل تغيير أي شيفرة.
  • تأكد أن المُبدئ كان نصك البرمجي وأن الرابط النهائي هو طرفك.
  • صنّف الاستجابة قبل أن تلمس المحلّل.
  • أصلح التوجيه أو الوصول أو التمثيل أو العقد، ولا تفعل ذلك أبدًا بإرخاء المحلّل.

مقالات ذات صلة