Python 怎么读取 JSON 文件?4 种方法和常见报错一次讲清

编程狮(w3cschool.cn) 2026-08-07 12:03:04 浏览数 (60)
反馈

在 Python 里读取 JSON 文件,最快的写法是先用 open 打开文件,再交给 json.load 解析,JSON 就会直接转成字典或列表,之后按键取值即可,全部只要三行。拿到一个 .json 配置文件或接口返回的数据文件时,不需要自己写解析逻辑。本文基于 Python 3.12 验证,整理读取 JSON 文件的 4 种常用方法——json.loadjson.loadspathlib 简写、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 里写的是小写的 truenull,到了 Python 里变成 TrueNone。所以判断时要写 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;想写得更短用 pathlibread_text;数据是一批结构化记录、要做统计,才上 pandas.read_json

要点带走:

  • load 处理文件对象,loads 处理字符串,差一个 s;
  • 打开文件永远显式写 encoding="utf-8",能避开大半乱码问题;
  • 报 JSONDecodeError 时先去看文件本身是不是合法 JSON,而不是怀疑代码;
  • 写回文件时加 ensure_ascii=False, indent=2,中文和格式都好看;
  • 不要用 eval 代替 json.loads

下一步,试着把一个真实的接口返回结果存成文件再读出来,把取值、遍历、写回完整练一遍。

延伸学习

想把 Python 这条线系统走完,可以按这个顺序推进:

  1. 先看 Python 开发方向,理清从语法基础到实际应用的整体路径;
  2. 想要成体系的课程安排,编程课程 里汇总了从入门到实战的多条路线。

常见问题

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。能解析成功就是合法的,捕获到异常说明格式有问题,异常信息里还会告诉你出错在第几行第几列。

0 人点赞