Python 读取 JSON 提示 UTF-8 BOM:先确认编码再解析
发布时间:2026/10/11 7:30:38 锦皓数字建站

大家好我是 SiKi老师。配置文件里明明只有一个 JSON 对象Python 却提示Unexpected UTF-8 BOM。这种报错和缺少逗号不是同一回事某些编辑器保存 UTF-8 文件时会在开头写入签名字节。先确认文件编码以及读取方式比直接删除文件、重新写默认值更容易保住原配置。本文在 Windows、Python 3.12.14 的独立临时目录里验证。文件只有自拟的音量字段没有真实账号或游戏存档。编码行为参照 Python 3.12 codecs 文档JSON 接口参照 json 文档。一 报错为什么落在文件开头UTF-8 签名的三个字节是EF BB BF。使用普通utf-8解码时开头的签名会成为字符串里的\ufeff。JSON 解析器拿到的是已经解码的字符串它不会把这个字符当作对象开头的花括号。我在实验中先写入签名字节再写入{volume: 10}。读取后字符串首字符的码点是0xfeff对这个字符串执行json.loads()报JSONDecodeError消息包含Unexpected UTF-8 BOM位置为第 1 行第 1 列。这只是一个明确构造的复现。不是所有发生在 1:1 的错误都由 BOM 引起。空文件同样可能在开头报错应看异常消息和实际编码不能只依据行列号猜结论。二 先验证读取方式不覆盖原件如果你确认这份文件是 UTF-8且可能包含开头签名可以让读取阶段使用utf-8-sigimportjsonfrompathlibimportPath pathPath(settings.json)textpath.read_text(encodingutf-8-sig)settingsjson.loads(text)我用同一份带签名文件验证这段得到{volume: 10}。这个编码在解码时会处理开头的 UTF-8 签名而不是让解析器接收它。这段代码没有写回文件。保留原件很重要如果接下来仍然报错至少可以比较读取方式而不会丢失最初的文件状态。不要在读配置失败的异常分支里悄悄覆盖源文件。三 没有签名的 UTF-8 文件怎么办同样的读取方式也能处理没有开头签名的 UTF-8 文本。我在实验中另写一份没有这三个字节的 JSON使用utf-8-sig读取并解析得到同一个字典。文件与读取组合本文隔离实验结果带 UTF-8 签名普通utf-8读取字符串开头保留\ufeffJSON 解析失败带 UTF-8 签名utf-8-sig读取得到音量字典无签名 UTF-8utf-8-sig读取得到音量字典这不意味着utf-8-sig可以自动识别任意编码。UTF-16、GBK 或已经损坏的字节流不在这个结论里。若文件实际采用其他编码应按文件的真实约定读取而不是给解析器不断换参数碰运气。四 json.load 也要把编码设在正确位置用文件对象读取时编码设置在打开文本文件的那一步importjsonwithopen(settings.json,encodingutf-8-sig)ashandle:settingsjson.load(handle)本文对带签名文件也验证了这种写法。不要把文件路径字符串传给json.loads()并期待它自动打开文件loads()解析的是传入内容load()则从提供的文件对象读取。确认解析成功后还要按项目要求检查顶层结构、字段类型和允许范围。能读出一个 JSON 值不等于音量或其他设置已经符合游戏的约定。本文没有实现配置恢复、范围检查或默认值策略。五 别把删除不可见字符当作通用修复我不建议对整段文本直接执行全局字符替换来消除报错。读取时处理开头签名和修改文本内容不是一件事全局删除可能改变合法字符串里的内容而且会掩盖编码来源。如果团队要统一文件格式应先约定保存编码再单独评审转换流程并保留原件。本文只验证读取带签名和无签名的 UTF-8 JSON没有验证编辑器自动保存、网络下载、并发写入或编码转换工具。实际排查时我会先记录异常消息、编码约定和读取代码再在独立副本上对照utf-8与utf-8-sig。这样能确认问题发生在解码还是 JSON 内容解析不必一开始就重建全部配置。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。