💡 开篇聊聊:为什么 JSON 这么重要?
你有没有发现,现在我们写 Python,几乎绕不开一个东西:JSON。
打开一个 API 接口,返回的是 JSON; 翻个配置文件,存储的是 JSON; 甚至你写个爬虫,扒下来的数据,十有八九也是 JSON。
可以说,JSON 就像数据世界的"英语",谁都得懂点。
而在 Python 里,处理 JSON 的关键武器就是自带的 json
模块。
很多人以为这东西很简单:不就是 dumps
、loads
吗?但真要用到复杂业务时,才会发现------里面藏着不少细节和坑。
今天我就带你,从最简单的入门,到高级的定制玩法,再到一些实战中的坑和小技巧,把 json
模块聊透。
这不是"搬运文档",而是把它放到真实开发场景里讲,让你学了就能用,且心里有数。

🚀 第一层:最基础的编码和解码
所有关于 JSON 的操作,基本都绕不开两个函数:
json.dumps()
------ 把 Python 对象转成 JSON 字符串json.loads()
------ 把 JSON 字符串转回 Python 对象
看个例子:
ini
import json
# Python 字典转换为 JSON 字符串
data = {"name": "Alice", "age": 25, "is_student": False}
json_str = json.dumps(data)
print(json_str) # 输出: {"name": "Alice", "age": 25, "is_student": false}
# JSON 字符串转换回 Python 字典
python_dict = json.loads(json_str)
print(python_dict["name"]) # 输出: Alice
是不是很直观?
不过注意了:
- Python 的
True
/False
会被转成true
/false
- Python 的
None
会变成null
- 而像集合、函数、类这种东西,默认是没法直接转的
这就像你要翻译语言,有些词能直译,有些就得解释甚至"改写"。
🚀 第二层:文件操作,别再傻乎乎自己写读写了
真实项目里,JSON 更多的不是存在内存里,而是保存在文件中。比如:
- 网站的配置文件
- 存储爬虫抓到的数据
- 或者日志和缓存
如果你用 dumps
再 write
,或者 read
再 loads
,那就太麻烦了。
Python 早就贴心地给你准备了两个函数:
json.dump()
------ 直接把对象写入文件json.load()
------ 直接从文件读出 JSON
看例子:
python
import json
# 将数据写入 JSON 文件
data = {"users": ["Alice", "Bob", "Charlie"], "count": 3}
with open("data.json", "w") as f:
json.dump(data, f)
# 从 JSON 文件读取数据
with open("data.json", "r") as f:
loaded_data = json.load(f)
print(loaded_data["users"]) # 输出: ['Alice', 'Bob', 'Charlie']
一句话总结:
dumps
/loads
是处理字符串 的,dump
/load
是处理文件的。
🚀 第三层:复杂对象怎么搞?
问题来了,假设你有一个自定义的类,比如用户对象,里面还有 datetime
时间字段。
默认序列化肯定报错,因为 JSON 根本不认识这些类型。
这时候就要用到 default 和 object_hook 参数,来自定义序列化/反序列化逻辑。
python
from datetime import datetime
import json
class User:
def __init__(self, name, join_date):
self.name = name
self.join_date = join_date
# 自定义序列化函数
def user_encoder(obj):
if isinstance(obj, User):
return {"name": obj.name, "join_date": obj.join_date.isoformat()}
elif isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
# 创建并序列化复杂对象
user = User("Alice", datetime.now())
json_str = json.dumps(user, default=user_encoder)
print(json_str) # 输出包含用户信息和日期的 JSON 字符串
这样,你就能"教会" JSON 该怎么理解你的类。
这一点在实际开发里太重要了,不然很多复杂数据根本保存不下来。
🚀 第四层:美观 vs 性能,两全其美
有时候,你要把 JSON 打印出来给人看,那必须排版整齐,不然眼睛要瞎;
但有时候,你是要把 JSON 传到网络上,数据越紧凑越好,不然带宽压力大。
这就用到 indent
、separators
、sort_keys
这些参数了。
ini
data = {"name": "Alice", "skills": ["Python", "SQL", "Data Analysis"], "age": 28}
# 美化输出,适合人类阅读
pretty_json = json.dumps(data, indent=4, sort_keys=True)
print(pretty_json)
# 优化输出,减少空格,适合网络传输
compact_json = json.dumps(data, separators=(",", ":"))
print(compact_json)
这就像两种不同的"写作文"风格:
- 给老师看的,排版整齐,字迹工整
- 给自己看的,速记,越省空间越好
场景不同,写法就不同。
🚀 第五层:实战中的坑和小技巧
很多人以为学了上面四层就完事了,结果一到实战就翻车。这里我总结几个常见坑:
1. JSON 解析错误
python
malformed_json = '{"name": "Alice", "age": }' # 缺少值
try:
data = json.loads(malformed_json)
except json.JSONDecodeError as e:
print(f"JSON 解析错误: {e}")
别让程序直接崩掉,记得用 JSONDecodeError
去兜底。
2. Unicode 问题
中文经常会被转成 \u4e2d\u6587
这种,看着很烦。解决办法:
ini
json.dumps(data, ensure_ascii=False)
3. 浮点数精度
有些场景对数字精度很敏感,注意 JSON 可能把 1.00000001 变成 1.0。
4. 循环引用
比如一个对象引用了自己,会无限递归报错。这种情况得小心数据结构,别瞎转。
🚀 最后一层:心法
其实,学工具不是目的。
真正的高手,关注的不只是"怎么用",而是:
- 什么时候该用 JSON?
- 怎么让 JSON 更高效?
- 怎么保证安全,不被奇怪的输入搞崩?
就像会开车,不只是会踩油门刹车,更是懂得什么时候该开快,什么时候该减速。
所以,当你下次处理 JSON 时,可以多问自己几个问题:
- 这个数据会不会特别大?
- 要不要给人看?要不要美化?
- 有没有潜在的安全风险?
带着这些思考去实践,你才会真的进阶。
🔥 总结
今天我们一路走下来,从最基础的 dumps
/ loads
,到文件操作 dump
/ load
,再到复杂对象、格式优化、常见陷阱。
掌握这些,你基本可以应付 90% 的场景了。剩下的 10%,需要你在实战中不断踩坑,不断优化。
记住:
- JSON 是数据世界的通用语言
json
模块是 Python 的翻译官- 会用只是第一步,懂得"何时、为何、如何用"才是真正的高手
如果你读完觉得收获不小,不妨点个赞,或者分享给身边也在写 Python 的朋友。
毕竟,学会一个模块只是开始,用它打开更多的可能性,才是真正的进阶。