BOM 會導致 JSON 解析失敗嗎
結論:UTF-8 BOM 是檔案開頭三個看不見的位元組 EF BB BF,JSON.parse 讀到就直接拋錯,而且錯誤位置通常報在第 1 行第 1 列,看起來像檔案是空的。

結論:先在檔案開頭查 EF BB BF 這三個位元組,再用「UTF-8 無 BOM」另存;服務端讀取上傳或第三方檔案時,第一步就剝掉開頭的 U+FEFF,別等解析報錯再排查。
會,而且是那種「檔案看起來完全正常,程式說第 1 行就錯了」的失敗。
現象長什麼樣
SyntaxError: Unexpected token in JSON at position 0
Unexpected character '\uFEFF'
注意報錯裡那個 是一個看不見的字元,位置 0,也就是第一個位元組。
用 cat 看不出來,用 hexdump -C file.json | head -1 就能看到開頭是 ef bb bf:
00000000 ef bb bf 7b 0a 20 20 22 61 22 3a 20 31 0a 7d 0a |...{ "a": 1.}.|
7b 才是 {。
為什麼會有 BOM
BOM 本來是 UTF-16 用來標記位元組序的,U+FEFF 放在檔案開頭。到了 UTF-8,位元組序只有一種,BOM 完全沒必要,但 Windows 記事本、部分 Excel 匯出、某些舊版 IDE 仍然預設寫進去,於是它就成了跨平台協作的經典坑。
RFC 8259 的態度很明確:JSON 文字必須以 UTF-8 編碼交換、實作不得添加 BOM,解析器「可以」忽略一個開頭的 BOM,但這不是義務。瀏覽器和 Node 的選擇是不忽略。
三種清除辦法
一、編輯器另存。 VS Code 右下角編碼處點一下,選「Save with Encoding → UTF-8」(不是「UTF-8 with BOM」)。
二、命令列剝掉。
sed -i '1s/^\xEF\xBB\xBF//' data.json
批次處理用 Node 更穩:
const fs = require('node:fs');
const text = fs.readFileSync('data.json', 'utf8').replace(/^\uFEFF/, '');
JSON.parse(text);
三、讀取時統一兜底。 服務端讀設定檔、解析上傳檔案時,第一步就 strip 掉 BOM,比事後排查便宜得多。Python 用 encoding='utf-8-sig' 讀就能自動處理。
順手避開的兩個相似問題
- 零寬空格 U+200B:從網頁複製 JSON 時行首可能帶上,報錯訊息類似但字元碼不同。
- 全形引號:中文輸入法寫出的
“key”,看起來和"key"幾乎一樣,JSON.parse會報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(Node 用 replace(/^\uFEFF/, ''),Python 用 encoding='utf-8-sig'),比事後定位便宜得多。