JSON 工具箱

BOM 會導致 JSON 解析失敗嗎

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

入門約 4 分鐘發佈於 2026-10-30更新於 2026-10-30
BOM 導致 JSON 解析失敗的原因與清除辦法

結論:先在檔案開頭查 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'),比事後定位便宜得多。

延伸閱讀