对象的序列化与反序列化
在真实开发中,我们几乎不会把数据存成零散的变量名。当你需要保存一份 AI 模型的超参数配置、向前端响应 JSON 数据,甚至让 Python 与 Java、Go 等异构系统通信时,都会面临同一个问题:如何用一种通用的格式,无损地交换复杂结构的数据?
答案就是 JSON —— 目前最流行的「数据桥接器」。这篇文章用最直接的方式,带你掌握 Python 中 JSON 的序列化与反序列化,以及两个让你事半功倍的实战工具。
1. JSON 是什么:从 JS 语法糖到“数据通行证”
JSON 全称 JavaScript Object Notation,最初只是 JavaScript 里写对象的简便语法。但由于它 纯文本、结构紧凑、跨语言全支持,很快取代冗长的 XML,成为 API 对接和配置文件的 事实标准。
JS ↔ Python 数据无缝映射表
JSON 的结构和 Python 字典、列表天然相通,支持无限层嵌套。不过为了跨语言兼容,JSON 的数据类型比 Python 少一些,对应关系见下表:
简单说,JSON 就是 Python 容器类型的「精简通用版」。掌握这张表,就能轻松完成内存对象与 JSON 文本的互转。
2. 核心工具:Python 内置 json 模块
Python 自带的 json 模块,提供了 内存对象 ↔ JSON(字符串/文件) 的双向转换能力。核心只有四个函数,记住它们的后缀就能分清用途:
记忆技巧:带 s 的是处理字符串(String),不带 s 的直接操作文件对象。
3. 实战演示:序列化与反序列化
下面用一个带嵌套结构、中文、布尔值、列表和空字段的复杂字典来演练完整的存取流程。这个例子模拟了一个 AI 平台(道满)的模型配置。
3.1 序列化:把对象变成 JSON
import json
# 模拟道满AI平台的用户模型配置
model_config = {
"model_name": "Daoman-Lite-7B",
"version": 1.2,
"is_active": True,
"author": "道满团队",
"supported_tasks": ["文本分类", "关键词提取", "情感分析"],
"hyperparameters": {
"max_seq_length": 512,
"batch_size": 16,
"learning_rate": 0.00005,
"dropout": None # 对应 JSON 的 null
}
}
# 1. 序列化为带格式的字符串(适合调试、打印、网络传输)
# indent=4: 缩进4个空格,方便阅读
# ensure_ascii=False: 不把中文转成 \uXXXX 编码
json_config_str = json.dumps(model_config, indent=4, ensure_ascii=False)
print("序列化后的字符串输出:")
print(json_config_str)
print("-" * 60)
# 2. 直接序列化到本地文件(持久化存储)
# 写文件时务必指定 encoding='utf-8',否则中文会乱码
with open("daoman_lite_config.json", "w", encoding="utf-8") as f:
json.dump(model_config, f, indent=4, ensure_ascii=False)
print("配置已保存到 daoman_lite_config.json!")
运行这段代码,你会看到格式清晰的 JSON 字符串,并且 daoman_lite_config.json 文件也已被正确写入。
3.2 反序列化:把 JSON 还原成对象
接下来把刚才保存的配置读回来,同时再演示一下如何从一段 JSON 字符串还原数据。
import json
# 1. 从 JSON 字符串反序列化
json_test_str = '{"name": "张三", "score": 99.5, "is_passed": true, "hobbies": null}'
parsed_dict = json.loads(json_test_str)
print("从字符串还原的字典:", type(parsed_dict), parsed_dict)
print("张三的分数类型:", type(parsed_dict["score"])) # 自动转成 float
print("-" * 60)
# 2. 从本地 JSON 文件反序列化
with open("daoman_lite_config.json", "r", encoding="utf-8") as f:
loaded_config = json.load(f)
print("从文件还原的作者:", loaded_config["author"])
print("支持的第一个任务:", loaded_config["supported_tasks"][0])
可以看出,无论是文件还是字符串,json.load 和 json.loads 都能将 JSON 数据完美还原为 Python 的原生字典和列表,并且数值类型自动匹配。
4. 加餐一:海量数据下的性能优化
当要处理百万级以上的 JSON 数据时(比如爬虫抓取的商品信息、批量 AI 推理结果),Python 内置的 json 模块可能会成为瓶颈。这时可以用 ujson —— 一个被称为“闪电解析器”的第三方库,速度通常比内置版快 3 到 10 倍。
4.1 pip 配置国内镜像(提速下载)
pip 是 Python 官方包管理工具,默认从国外 PyPI 下载,国内访问经常很慢。建议先配置清华镜像:
# 永久配置清华镜像(推荐)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
4.2 安装并使用 ujson
安装 ujson 后,你只需要修改一行导入语句,其余代码完全兼容内置 json 模块的四核心函数。
# 原代码只需修改导入,其余不动
import ujson as json # 将 ujson 别名为 json
# 前面定义的 model_config 可以直接使用,所有操作完全兼容
json_str = json.dumps(model_config, indent=4, ensure_ascii=False)
loaded = json.loads(json_str)
print("使用 ujson 解析,性能大幅提升!")
pip 常用命令速查表
5. 加餐二:实战调用公开 JSON API
如今绝大多数 API 都通过 HTTP/HTTPS 返回 JSON 数据。Python 内置的 urllib 使用起来比较繁琐,更推荐使用 requests 库——它被称为“最优雅的 HTTP 库”,内置 JSON 解析方法。
5.1 安装 requests
5.2 调用新闻 API(示例)
下面以天聚数行的免费国内新闻 API 为例(需自行申请免费密钥,日调用量 100 次)。将代码中的 YOUR_API_KEY 替换为你自己的密钥即可。
import requests
# 替换成你自己的 API 密钥
API_KEY = "YOUR_API_KEY"
NEWS_API_URL = f"http://api.tianapi.com/guonei/?key={API_KEY}&num=5" # num=5 取5条
try:
# 发送 GET 请求
resp = requests.get(NEWS_API_URL)
# 检查 HTTP 状态码是否为 200
resp.raise_for_status()
# 关键一步:requests 内置 json() 方法,直接将响应解析为 Python 字典
news_data = resp.json()
# 解析业务状态码
if news_data["code"] == 200:
print("📰 今日国内热点新闻(前5条):")
print("=" * 80)
for idx, news in enumerate(news_data["newslist"], 1):
print(f"{idx}. 标题:{news['title']}")
print(f" 链接:{news['url']}")
print(f" 发布时间:{news['ctime']}")
print("-" * 80)
else:
print(f"❌ API 返回错误:{news_data['msg']}")
except requests.exceptions.RequestException as e:
print(f"❌ 请求失败:{e}")
resp.json() 这个调用背后,其实就是对响应内容执行了 json.loads(),省去了我们手动解析的步骤,非常方便。
6. 总结
今天我们只聚焦了三件事,但已经足够覆盖日常开发中 90% 的 JSON 场景:
- JSON 的定位:跨语言、纯文本、结构紧凑的“数据桥接器”
- Python 内置 json 模块四大金刚:
dumps/dump(序列化)、loads/load(反序列化)
- 两个提效小工具:
- ujson:让大型 JSON 处理快如闪电
- requests:优雅地调用 JSON API
最后提醒两个最容易出错的点:
- 写 JSON 文件时 务必指定
encoding='utf-8',否则中文一定乱码。
- JSON 的键必须是 双引号字符串。虽然 Python 的单引号键在序列化时会自动转换,但在手动拼写 JSON 字符串时,千万不要写出单引号。
掌握这些,你就可以放心地在各种项目中使用 JSON 来存储、传输和交换数据了。