
先说结论,再说为什么。
Python 读取 JSON 文件,核心代码其实只有两行:
import json
with open("data.json", "r", encoding="utf-8") as file:
data = json.load(file)真正让初学者卡住的,往往不是“怎么读取”,而是读取之后不知道 data 到底是什么,也不知道该用键名、下标还是循环取值。
这事儿其实没那么玄。先把 JSON 和 Python 数据类型的对应关系弄清楚,后面的代码就顺了。
新建一个 user.json 文件:
{
"name": "沈砚",
"age": 35,
"active": true,
"skills": ["Python", "Scrapy", "Playwright"],
"profile": {
"city": "杭州",
"job": "数据工程师"
},
"projects": [
{
"name": "网页采集",
"status": "running"
},
{
"name": "语料清洗",
"status": "finished"
}
]
}读取代码如下:
import json
with open("user.json", "r", encoding="utf-8") as file:
data = json.load(file)
print(data)
print(type(data))输出的类型是:
<class 'dict'>因为这份 JSON 最外层是 {},所以读进 Python 后是字典 dict。如果最外层是 [],得到的就是列表 list。
我刚开始带新人写采集脚本时,会让他先打印一次 type(data)。这一步看起来有点笨,却能避开一半的提取错误——连顶层结构都没看清,就急着写 data["name"],报错并不奇怪。
字典可以直接通过键名取值:
name = data["name"]
age = data["age"]
print(name)
print(age)输出:
沈砚
35这里有个前提:你确定字段存在。
如果执行下面这行代码:
phone = data["phone"]Python 会报错:
KeyError: 'phone'字段可能缺失时,我更习惯用 get():
phone = data.get("phone", "未填写")
print(phone)找不到 phone,程序会返回默认值“未填写”,不会直接停掉。
说白了,方括号适合必填字段,get() 更适合接口数据、采集结果和用户配置——这些数据从来没有看上去那么规整。
现在要获取 profile 里的城市,可以连续写两个键名:
city = data["profile"]["city"]
print(city)输出:
杭州如果中间字段不一定存在,可以这样写:
profile = data.get("profile") or {}
city = profile.get("city", "未知城市")
print(city)为什么不直接写 data.get("profile", {})?
因为当 profile 不存在时,它确实会返回空字典;只不过,当 profile 存在但值为 null 时,Python 得到的是 None,继续调用 .get() 仍然会报错。加上 or {},这一层才算兜住了。
这地方很多人踩坑。
skills 在 JSON 中是数组,读进 Python 后会变成列表:
skills = data.get("skills", [])
print(skills)
print(skills[0])输出:
['Python', 'Scrapy', 'Playwright']
Python提取全部技能,可以直接遍历:
for skill in skills:
print(skill)如果只想取第一个元素,最好先判断列表是否为空:
if skills:
print(skills[0])否则空列表访问 skills[0],会触发 IndexError。
采集接口里更常见的是这种结构:
"projects": [
{
"name": "网页采集",
"status": "running"
},
{
"name": "语料清洗",
"status": "finished"
}
]可以先遍历列表,再从每个字典里取字段:
projects = data.get("projects", [])
for project in projects:
name = project.get("name", "未命名")
status = project.get("status", "unknown")
print(name, status)如果只想保留状态为 running 的项目:
running_projects = [
project
for project in projects
if project.get("status") == "running"
]
print(running_projects)往下拆一层看,这段代码做了三件事:遍历项目、检查状态、把符合条件的完整对象放进新列表。数据量不大时,列表推导式很省事;逻辑一旦超过两三个条件,我还是建议老老实实写普通循环,可读性比少写几行重要。
json.load() 接收文件对象:
with open("user.json", "r", encoding="utf-8") as file:
data = json.load(file)json.loads() 接收 JSON 字符串:
json_text = '{"name": "沈砚", "age": 35}'
data = json.loads(json_text)简单记:
json.load()。json.loads()。多出来的那个 s,可以理解成 string。
最常见的不是 Python 有问题,而是文件不符合标准 JSON:
// 或 # 注释。true、false、null 写成了 Python 的 True、False、None。遇到 Unexpected UTF-8 BOM,可以试一下:
with open("user.json", "r", encoding="utf-8-sig") as file:
data = json.load(file)Python 读取 JSON 不难。我的习惯是先确认顶层类型,再判断字段是必填还是可选,碰到嵌套对象就一层一层取,不追求把所有逻辑挤进一行。
代码写短不等于写稳。尤其是第三方数据,别对它太有信心。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。