You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python解析manifest.json触发JSONDecodeError错误求助

UTF-8 BOM导致JSON解析失败的解决办法

问题场景

开发Mod管理器时,读取mod的manifest.json文件获取名称、版本等信息时触发JSONDecodeError,输出显示文件开头存在字符,即使手动重写文件问题依然存在。

相关文件内容

manifest.json

{
    "name": "HookGenPatcher",
    "version_number": "0.0.5",
    "website_url": "https://github.com/harbingerofme/Bepinex.Monomod.HookGenPatcher",
    "description": "Generates MonoMod.RuntimeDetour.HookGen's MMHOOK file during the BepInEx preloader phase.",
    "dependencies": []
}

原始代码

from json import JSONDecoder
import os
from zipfile import is_zipfile, ZipFile

json = JSONDecoder()

PLUGIN_PATH: str = "./mods"

plugins: dict[str: dict[str: str]] = {}

for mod in os.listdir(path=PLUGIN_PATH):
      mod_path: str = f"{PLUGIN_PATH}/{mod}"
      if is_zipfile(filename=mod_path):
            folder_path: str = ".".join(mod_path.split(sep=".")[:-1])
            os.mkdir(path=folder_path)

            mod_zip = ZipFile(file=mod_path)
            mod_zip.extractall(path=folder_path)
            mod_zip.close()

            os.remove(path=mod_path)

      with open(file=f"{mod_path}/manifest.json", mode="r") as f:
            x: str = f.read()
            y: list = []

            for line in x.splitlines():
                  y.append(line.strip())

            y = "".join(y)

            print(y)

            mod_json: dict = json.decode(s=y)

      plugins[mod] = mod_json

print(plugins)

报错信息

{"name": "HookGenPatcher","version_number": "0.0.5","website_url": "https://github.com/harbingerofme/Bepinex.Monomod.HookGenPatcher","description": "Generates MonoMod.RuntimeDetour.HookGen's MMHOOK file during the BepInEx preloader phase.","dependencies": []}

Traceback (most recent call last):
  File "d:\OneDrive\Code\BetterLCMods\main.pyw", line 58, in <module>
    mod_json: dict = json.decode(s = y)
                     ^^^^^^^^^^^^^^^^^^
  File "E:\Python\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\Python\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

原因分析

文件开头的是UTF-8字节顺序标记(BOM),部分编辑器(如Windows记事本)保存UTF-8文件时会自动添加该标记。Python默认以utf-8编码读取文件时不会去除BOM,导致JSON解析器无法识别开头的无效字符,触发错误。此外,原始代码解压zip后未更新mod_path为文件夹路径,可能导致后续文件读取异常。

解决方案

方法1:读取文件时指定utf-8-sig编码

Python的utf-8-sig编码会自动识别并去除UTF-8 BOM,是最简便的解决方式:

with open(file=f"{mod_path}/manifest.json", mode="r", encoding="utf-8-sig") as f:
    mod_json: dict = json.load(f)

方法2:手动去除字符串开头的BOM

如果无法指定编码,可手动检查并移除BOM标记:

with open(file=f"{mod_path}/manifest.json", mode="r") as f:
    x: str = f.read()
    if x.startswith('\ufeff'):
        x = x[1:]
    mod_json: dict = json.decode(x)

补充修复:解压后更新mod_path

解压zip后,需将mod_path更新为解压后的文件夹路径,否则会找不到manifest.json:

if is_zipfile(filename=mod_path):
    folder_path: str = ".".join(mod_path.split(sep=".")[:-1])
    os.mkdir(path=folder_path)

    mod_zip = ZipFile(file=mod_path)
    mod_zip.extractall(path=folder_path)
    mod_zip.close()

    os.remove(path=mod_path)
    mod_path = folder_path

优化后的完整代码

from json import load as json_load
import os
from zipfile import is_zipfile, ZipFile

PLUGIN_PATH: str = "./mods"
plugins: dict[str, dict[str, str | list]] = {}

for mod in os.listdir(PLUGIN_PATH):
    mod_path: str = os.path.join(PLUGIN_PATH, mod)
    if is_zipfile(mod_path):
        folder_path: str = os.path.splitext(mod_path)[0]
        os.makedirs(folder_path, exist_ok=True)

        with ZipFile(mod_path) as mod_zip:
            mod_zip.extractall(folder_path)
        
        os.remove(mod_path)
        mod_path = folder_path

    manifest_path = os.path.join(mod_path, "manifest.json")
    if os.path.exists(manifest_path):
        with open(manifest_path, "r", encoding="utf-8-sig") as f:
            mod_json = json_load(f)
        plugins[mod] = mod_json

print(plugins)

内容的提问来源于stack exchange,提问作者PhaseAmaze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:05:14