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(Byte Order Mark)本来是 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」)。Sublime、Notepad++ 都有类似选项。
二、命令行剥掉。 处理单个文件:
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'),比事后定位便宜得多。
相关工具
- JSON 格式化与校验:粘贴后直接给出出错行列,BOM 会在第一个字符处失败
- JSON 文件是什么、怎么打开:编码与打开方式的常识部分