根本原因是json.dumps()默认ensure_ascii=true导致中文转义,且xml文件编码未正确指定或写入json时未设utf-8编码。需三步:确认源xml编码→用对应encoding读取→parse后dumps时设ensure_ascii=false并以utf-8写入。

xmltodict.parse() 返回的字典含中文但 json.dumps() 出现乱码
根本原因不是 xmltodict 本身出错,而是 json.dumps() 默认不启用中文字符转义,且未指定 ensure_ascii=False —— 它会把所有非 ASCII 字符(比如中文)强制编码成 \uXXXX 形式,看起来像乱码,实际是 Unicode 转义序列。
- 如果你用
print(json.dumps(data))看到一堆\u4f60\u597d,这不是乱码,是 JSON 标准行为;真正要写入文件或传给前端时才需要可读中文 - 必须显式传参
ensure_ascii=False,否则无论输入多干净,输出都是转义形式 - 如果原始 XML 文件本身是 GBK 编码,而你没指定
encoding给xmltodict.parse(),那第一步就已损坏——此时json.dumps再怎么设也救不回来
从文件读取 XML 时 encoding 参数漏设导致后续全乱
xmltodict.parse() 接收字符串,不自动探测编码。若 XML 文件是 GBK 或 GB2312,直接用 open(path).read()(默认 UTF-8)读取,就会解码失败,产生 UnicodeDecodeError 或静默乱码。
- 先确认 XML 文件真实编码:可用命令行
file -i filename.xml(Linux/macOS)或 VS Code 底部状态栏查看 - 读取时务必显式指定:
with open('data.xml', 'r', encoding='gbk') as f: xml_str = f.read() - 再传给
xmltodict.parse(xml_str);跳过这步,后面所有 JSON 操作都在错误数据上叠加 - 如果 XML 声明里写了
<?xml version="1.0" encoding="GBK"?>,xmltodict不会自动按它解码,仍需你手动处理
json.dumps() 写入文件后打开仍是乱码
即使加了 ensure_ascii=False,写入文件时若没指定文件编码,Python 默认用系统 locale(Windows 常为 GBK),而编辑器(如 VS Code、Notepad++)可能按 UTF-8 解析,显示就错位。
- 写文件必须配对指定编码:
with open('out.json', 'w', encoding='utf-8') as f: f.write(json.dumps(data, ensure_ascii=False, indent=2)) - 不要用
open(...).write(...)两步分开,避免中间字符串隐式转换 - 检查目标文件是否真为 UTF-8:用
file -i out.json验证,或在编辑器里看右下角编码标识 - 如果下游系统(如 Java 后端)要求 BOM 头,需手动加
'\ufeff'前缀,但绝大多数现代 JSON 解析器不需要也不推荐
嵌套层级深、含特殊字符时 json.dumps() 报错
xmltodict 可能将 XML 注释、CDATA、属性等转为特殊结构(如 @ 开头键名、#text 键),若其中混入不可 JSON 序列化的类型(如 datetime、自定义对象),json.dumps() 直接抛 TypeError。
立即学习“Python免费学习笔记(深入)”;
- 常见报错:
Object of type datetime is not JSON serializable—— 检查 XML 是否含时间戳字段,被解析为datetime对象 - 简单过滤:用
default参数兜底,例如json.dumps(data, default=str, ensure_ascii=False),把所有非标类型转成字符串 - 更稳妥做法:先递归遍历字典,把
datetime、bytes等转成 ISO 格式字符串或 base64,而不是依赖default=str(它会把bytes转成b'xxx'这种不可逆形式) - 注意:XML 属性值默认变成字符串,但某些 parser 配置可能保留原始类型,需实测验证
xmltodict.parse() 得字典 → json.dumps(..., ensure_ascii=False) + open(..., encoding='utf-8') 写入。漏掉任一环,中文都会“消失”。










