هل يكسر BOM تحليل JSON
الخلاصة: BOM بترميز UTF-8 هو ثلاثة بايتات غير مرئية، فيفشل JSON.parse عند الحرف الأول ويبلّغ عن السطر 1 العمود 1، ما يجعل الملف يبدو فارغًا أو مقطوعًا.

الخلاصة: تحقق من البايتات الثلاثة الأولى بحثًا عن EF BB BF وأعد الحفظ بترميز UTF-8 دون BOM؛ وعلى الخادم، أزل U+FEFF البادئ قبل تحليل أي ملف مرفوع أو من طرف ثالث بدلًا من تشخيص الفشل لاحقًا.
نعم — وينتج أكثر أخطاء التحليل إرباكًا، لأن الملف يبدو سليمًا تمامًا.
ما تراه
SyntaxError: Unexpected token in JSON at position 0
Unexpected character '\uFEFF'
ذلك الحرف في الرسالة غير مرئي. الموضع 0 يعني البايت الأول تمامًا.
cat لا يظهر شيئًا غير عادي. hexdump -C file.json | head -1 يظهر:
00000000 ef bb bf 7b 0a 20 20 22 61 22 3a 20 31 0a 7d 0a |...{ "a": 1.}.|
7b هو {. والبايتات الثلاثة قبله هي BOM.
من أين تأتي BOM
وُجدت علامة ترتيب البايتات لـUTF-16، حيث كان ترتيب البايتات يتفاوت فعلًا. UTF-8 له ترتيب بايتات واحد، لذا BOM مجرد عبء — لكن Notepad على Windows، وبعض صادرات Excel، وقليل من IDEs الأقدم ما زالت تكتبه افتراضيًا.
RFC 8259 لا لبس فيه: JSON المتبادل بين الأنظمة يجب أن يكون UTF-8، ويجب ألّا تضيف التطبيقات BOM. المحللات قد تتجاهل BOM البادئ لكنها غير ملزمة بذلك. المتصفحات وNode تختار عدم تجاهله.
ثلاث طرق للتخلص منه
احفظ دون BOM. في VS Code، انقر الترميز في شريط الحالة واختر "Save with Encoding ← UTF-8"، لا "UTF-8 with BOM".
أزله من الـshell.
sed -i '1s/^\xEF\xBB\xBF//' data.json
أزله عند القراءة. هذا الإصلاح المتين لأي شيء يقبل ملفات مرفوعة أو من طرف ثالث:
const text = require('node:fs').readFileSync('data.json', 'utf8').replace(/^\uFEFF/, '');
JSON.parse(text);
في Python، open(path, encoding='utf-8-sig') يتعامل معه تلقائيًا.
مشكلتان متشابهتان
- المسافة صفرية العرض (U+200B) — تُلتقط عند نسخ JSON من صفحة ويب؛ العَرَض مطابق، ونقطة الترميز مختلفة.
- الاقتباسات بعرض كامل — IME صيني يحوّل
"key"إلى“key”، الذي يبدو متطابقًا تقريبًا لكنه يفشل كـUnexpected token “.
الثلاثة جميعًا أخطاء أحرف غير مرئية. والتشخيص دائمًا واحد: أفرغ البايتات الأولى بصيغة ست عشرية بدلًا من التحديق في النص.
الأسئلة الشائعة
كيف أعرف هل يبدأ ملف بـBOM؟
cat لا يظهر شيئًا، لذا نفّذ hexdump -C file.json | head -1. إن بدأ الخرج بـef bb bf، فالملف يحتوي BOM؛ ويجب أن يأتي 7b (أي {) أولًا في ملف UTF-8 نظيف.
لماذا يشير الخطأ دائمًا إلى السطر 1، العمود 1؟
يجلس BOM قبل كل شيء آخر، فيكون أول حرف يقرأه المحلل هو U+FEFF. لذا يقع الفشل في بداية الملف، ما يجعل الملف يبدو فارغًا.
هل يجب أن أزيل BOM قبل التحليل؟
نعم. عندما يقرأ خادم تهيئة أو يحلل ملفات مرفوعة، أزل U+FEFF البادئ أولًا — replace(/^\uFEFF/, '') في Node، وencoding='utf-8-sig' في Python — وهذا أرخص بكثير من تشخيصه لاحقًا.