本文要点
以 UTF-8 编码保存和读取 JSON 文件
JSONDecodeError 是 ValueError 的子类
默认情况下,json 模块不会报错,而是只保留最后一个键值对

本文目录
JSON文件读取前的准备
本指南只讨论读取你自己创建的 JSON 文件,不涉及从网络或他人处获取的数据。JSON 是由 RFC 7159 和 ECMA-404 规定的轻量级数据交换格式,Python 的 json 模块提供了相应的编码器和解码器。在开始前,请确保你已安装 Python 3,并准备一个用于练习的目录。
重要提醒:操作前请备份你的文件,避免意外覆盖或丢失。本指南中的示例文件均为自建,不会修改系统文件或执行删除操作。
关于编码:json.load 的 fp 参数可以是文本文件或二进制文件。当传入二进制文件时,输入编码应为 UTF-8、UTF-16 或 UTF-32。RFC 要求 JSON 使用 UTF-8、UTF-16 或 UTF-32 表示,其中 UTF-8 是推荐默认值。为了明确和可移植,本指南建议始终以 UTF-8 编码保存和读取 JSON 文件。
读取与格式检查方法
1. 创建一个自建的 JSON 文件,例如 data.json,内容如下(注意使用双引号,不要使用单引号或尾随逗号):
{
"name": "示例项目",
"version": 1,
"tags": ["python", "json"],
"active": true
}2. 使用 Python 的 json.load 读取该文件。以下代码以 UTF-8 编码打开文件,并打印解析后的 Python 对象:
import json
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data)
print(type(data))运行后,你会看到类似 {'name': '示例项目', 'version': 1, 'tags': ['python', 'json'], 'active': True} 的输出,类型为 dict。
3. 处理格式错误。如果 JSON 文件格式不正确,json.load 会抛出 json.JSONDecodeError 异常。你可以用 try...except 捕获它,并利用异常对象的属性定位问题:
import json
try:
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f'JSON 格式错误:{e.msg}')
print(f'错误位置:第 {e.lineno} 行,第 {e.colno} 列')
print(f'出错字符索引:{e.pos}')JSONDecodeError 是 ValueError 的子类,其额外属性包括 msg、doc、pos、lineno 和 colno,可以帮助你定位错误位置。
4. 故意制造一个错误来观察效果。将 data.json 中的某个键值对末尾的逗号去掉,或者把双引号改成单引号,再次运行上述代码,就会看到具体的错误信息。
常见格式错误处理
问:为什么读取时提示编码错误?
答:如果数据不是 UTF-8、UTF-16 或 UTF-32 编码,可能会引发 UnicodeDecodeError。建议统一使用 UTF-8 保存文件,并在 open 时指定 encoding='utf-8'。
问:如果 JSON 文件中有重复的键怎么办?
答:RFC 规定 JSON 对象中的名称应当唯一,但未强制规定如何处理重复名称。默认情况下,json 模块不会报错,而是只保留最后一个键值对。例如 '{"x": 1, "x": 2, "x": 3}' 解析后得到 {'x': 3}。如果需要自定义处理,可以使用 object_pairs_hook 参数。
问:能否读取包含 NaN 或 Infinity 的文件?
答:RFC 不允许表示无穷或 NaN 数值。尽管如此,默认情况下 json 模块接受并输出 Infinity、-Infinity 和 NaN,就好像它们是合法的 JSON 数字字面量。在反序列化器中,可以使用 parse_constant 参数来改变这一行为。
示例文件操作限制
1. 本指南仅操作自建示例文件,请勿对重要文件直接进行修改。操作前务必备份。
2. 不要执行危险删除或系统修改命令。本指南不涉及此类操作。
3. 解析来自不可信来源的 JSON 数据时需谨慎,恶意 JSON 字符串可能导致解码器消耗大量 CPU 和内存资源。建议限制待解析数据的大小。
4. 关于编码:json 模块的序列化器默认 ensure_ascii=True,会转义非 ASCII 字符。反序列化时,如果传入二进制文件,输入编码应为 UTF-8、UTF-16 或 UTF-32。本指南明确使用 UTF-8,但不声称这是默认编码。
5. RFC 禁止在 JSON 文本开头添加字节顺序标记(BOM),本模块的序列化器不会在输出中添加 BOM。本模块的反序列化器在输入存在初始 BOM 时会引发 ValueError。
6. 本指南中的示例仅用于演示读取和错误处理,不涉及网络请求、文件写入或系统配置更改。
观看知识要点视频 18 秒
18秒无旁白要点导览,文字来自已审核正文;完整步骤、条件及参考资料见下方。
参考资料
以下原始资料提供本文依据;请结合日期、适用条件和产品说明查阅。
请结合原始资料的适用条件阅读。
返回表格与数据 →