在 Python 里读取 JSON 文件,最快的写法是先用 open 打开文件,再交给 json.load 解析,JSON 就会直接转成字典或列表,之后按键取值即可,全部只要三行。拿到一个 .json 配置文件或接口返回的数据文件时,不需要自己写解析逻辑。本文基于 Python 3.12 验证,整理读取 JSON 文件的 4 种常用方法——json.load、json.loads、pathlib 简写、pandas.read_json,说明各自适合什么场景,并把新手最常撞上的中文乱码、JSONDecodeError、路径找不到这几类报错逐个拆开讲。看完你能在任何项目里稳稳地把 JSON 数据取出来。今天这篇文章,编程狮就把这块讲透。
一、先说结论:json.load 三行搞定
标准写法长这样:
import json
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
print(data)
这段代码做了三件事:open() 以只读方式打开文件并指定 UTF-8 编码,with 保证文件用完自动关闭,json.load(f) 把文件里的内容解析成 Python 对象。解析完成后,JSON 的对象 {} 变成 Python 字典,数组 [] 变成列表,就可以直接用了。
假设 config.json 内容如下:
{
"name": "编程狮",
"port": 8080,
"debug": true,
"tags": ["python", "json"]
}
那么读完之后:
print(data["name"]) # 编程狮
print(data["port"] + 1) # 8081
print(type(data)) # <class 'dict'>
print(data["tags"][0]) # python
注意 data["port"] 拿到的是整数 8080,不是字符串——json.load 会自动做类型转换。刚接触文件操作的同学,可以先把 Python3 教程 里文件读写和字典那两章过一遍,后面会顺很多。
1.1 JSON 类型和 Python 类型的对应关系
解析时的转换规则是固定的,记住这张表就不会踩坑:
| JSON | Python |
|---|---|
object {} |
dict |
array [] |
list |
| string | str |
| number(整数) | int |
| number(小数) | float |
| true / false | True / False |
| null | None |
最容易搞混的是最后两行:JSON 里写的是小写的 true、null,到了 Python 里变成 True、None。所以判断时要写 if data["debug"]:,而不是拿它和字符串 "true" 比较。
二、方法一与方法二:json.load 和 json.loads 的区别
这两个函数名只差一个字母 s,是新手最常混淆的地方。记法很简单:loads 的 s 指 string,处理字符串;没有 s 的 load 处理文件对象。
2.1 json.loads:先读成字符串再解析
如果你已经有一段 JSON 字符串(比如从接口响应、数据库字段、环境变量里拿到的),就用 json.loads():
import json
text = '{"name": "编程狮", "port": 8080}'
data = json.loads(text)
print(data["name"]) # 编程狮
读取 JSON 文件时也可以走这条路,先把文件读成字符串,再解析:
with open("config.json", "r", encoding="utf-8") as f:
text = f.read()
data = json.loads(text)
结果和 json.load(f) 完全一样,只是多了一步。什么时候需要这样绕一下?当你想在解析前先对文本做处理时——比如去掉 BOM、替换某些占位符、或者先打印出来看看文件到底长什么样。函数参数记不清时,Python 速查手册 里能快速翻到 json 模块的常用用法。
2.2 两者怎么选
- 手里是文件对象 → 用
json.load(f); - 手里是字符串 → 用
json.loads(text); - 只是想读文件、没有额外处理需求 → 直接
json.load,少写一行。
三、方法三:pathlib 一行读取(推荐的现代写法)
Python 3.4 之后引入的 pathlib,能让读取 JSON 文件的代码更短:
import json
from pathlib import Path
data = json.loads(Path("config.json").read_text(encoding="utf-8"))
print(data)
Path("config.json").read_text() 直接把整个文件读成字符串,自动帮你处理打开和关闭,再交给 json.loads 解析。一行就完成了原来三行的事。
pathlib 的另一个好处是处理路径更省心。Windows 用反斜杠、Linux 用正斜杠,用 Path 拼接就不用管这个差异:
from pathlib import Path
# 自动适配当前系统的分隔符
config_path = Path("data") / "user" / "config.json"
print(config_path.exists()) # 先判断文件在不在
JSON 这个格式本身源自 JavaScript 的对象表示法(JavaScript Object Notation),后来因为轻量、跨语言而被广泛采用。想了解它最初的样子,可以看 JavaScript 教程 里对象和 JSON 部分的说明,理解格式规则后再回头看 Python 这边会更清楚。
四、方法四:pandas.read_json 与四种方法怎么选
4.1 数据是表格结构时用 pandas
如果 JSON 里存的是一批结构一致的记录,比如:
[
{"name": "小明", "score": 90},
{"name": "小红", "score": 95}
]
用 pandas 读进来会直接变成表格,方便做统计和筛选:
import pandas as pd
df = pd.read_json("scores.json")
print(df)
print(df["score"].mean()) # 92.5
需要先安装:pip install pandas。注意这是个第三方库,只为读一个配置文件而装它没必要,做数据分析时才值得。
4.2 每行一个 JSON 的文件怎么读
日志文件常见这种格式(叫 JSON Lines,后缀多为 .jsonl),整个文件不是一个合法 JSON,不能直接 json.load:
import json
records = []
with open("logs.jsonl", "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line: # 跳过空行
records.append(json.loads(line))
print(len(records))
逐行解析即可。遇到不认识的概念名词,可以在 编程词典 里按词查一遍再继续。
4.3 四种方法对照
| 方法 | 适合场景 | 是否需装第三方库 |
|---|---|---|
json.load(f) |
读配置、读单个 JSON 文件 | 否 |
json.loads(s) |
手上已经是字符串 | 否 |
Path.read_text() + loads |
想写得更简洁 | 否 |
pandas.read_json() |
一批结构化记录、要做分析 | 是 |
4.4 常见报错怎么解决
中文变成 \u7f16\u7a0b:这不是报错,是 JSON 的转义写法。json.load 读出来时会自动还原成中文,能正常 print 就没问题。只有在写回文件时才需要加参数:
with open("out.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
ensure_ascii=False 让中文原样保存,indent=2 让文件带缩进、方便人看。
中文乱码或 UnicodeDecodeError:几乎都是 open() 没写 encoding="utf-8"。Windows 下 Python 默认用系统编码(常为 GBK),读 UTF-8 文件就会出错。养成每次都显式写编码的习惯即可。
报 JSONDecodeError:Expecting value: line 1 column 1 (char 0):这条 JSONDecodeError 的意思是"第一个字符就不合法",常见原因有三个——文件是空的、文件里根本不是 JSON(比如接口返回了一段 HTML 报错页)、或者文件带 UTF-8 BOM 头。判断方法很直接:先把文件用 f.read() 原样打印出来看看开头是什么,再决定怎么处理。属于第三种情况时,把编码换成 encoding="utf-8-sig" 就能解决,这个参数会自动跳过 BOM 头。
FileNotFoundError:路径是相对于运行脚本时所在的目录,不是脚本文件所在目录。用 Path(__file__).parent / "config.json" 可以稳定定位到脚本同级的文件。
单引号导致解析失败:{'name': '编程狮'} 是合法的 Python 字典字面量,但不是合法 JSON——JSON 规定字符串必须用双引号。这种文本用 json.loads 会直接报错,需要先修正数据源。
⚠️ 注意:不要用
eval()去解析 JSON 文本。它虽然能"跑通"单引号的情况,但会执行文本里的任意代码,读到不可信文件时存在安全风险。
总结
在 Python 里读取 JSON 文件,记住主线就够了:with open(..., encoding="utf-8") 打开,json.load(f) 解析,拿到字典或列表后按键取值。手上是字符串就换成 json.loads;想写得更短用 pathlib 的 read_text;数据是一批结构化记录、要做统计,才上 pandas.read_json。
要点带走:
load处理文件对象,loads处理字符串,差一个 s;- 打开文件永远显式写
encoding="utf-8",能避开大半乱码问题; - 报 JSONDecodeError 时先去看文件本身是不是合法 JSON,而不是怀疑代码;
- 写回文件时加
ensure_ascii=False, indent=2,中文和格式都好看; - 不要用
eval代替json.loads。
下一步,试着把一个真实的接口返回结果存成文件再读出来,把取值、遍历、写回完整练一遍。
延伸学习
想把 Python 这条线系统走完,可以按这个顺序推进:
- 先看 Python 开发方向,理清从语法基础到实际应用的整体路径;
- 想要成体系的课程安排,编程课程 里汇总了从入门到实战的多条路线。
常见问题
Q:json.load 和 json.loads 到底怎么记?
A:看参数类型。load 接收的是文件对象(open() 返回的那个 f),loads 接收的是字符串,s 就代表 string。写代码时先看手上拿的是什么,就不会选错。
Q:读出来的中文显示成 \u 开头的编码怎么办?
A:如果是 print(data) 打印整个字典时出现的,那是 Python 显示容器时的默认行为,print(data["name"]) 单独取值就是正常中文。如果是写回文件时出现的,加上 ensure_ascii=False 即可。
Q:JSON 文件很大,一次性读会不会内存爆掉?
A:标准库 json 是一次性全量解析的。文件达到几百兆时,建议改用 JSON Lines 格式逐行处理,或者使用 ijson 这类支持流式解析的第三方库。
Q:怎么判断一段文本是不是合法 JSON?
A:用 try 包住 json.loads,捕获 json.JSONDecodeError。能解析成功就是合法的,捕获到异常说明格式有问题,异常信息里还会告诉你出错在第几行第几列。

免费 AI IDE



