对象的序列化与反序列化

在真实开发中,我们几乎不会把数据存成零散的变量名。当你需要保存一份 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 类型核心说明
objectdict键必须是双引号包裹的字符串
arraylist有序可变序列
stringstr统一 Unicode 编码,中文没问题
numberint / float自动区分整数和浮点数
booleanbooltrueTruefalseFalse严格区分大小写!
nullNonePython 里的空对象占位符

简单说,JSON 就是 Python 容器类型的「精简通用版」。掌握这张表,就能轻松完成内存对象与 JSON 文本的互转。


2. 核心工具:Python 内置 json 模块

Python 自带的 json 模块,提供了 内存对象 ↔ JSON(字符串/文件) 的双向转换能力。核心只有四个函数,记住它们的后缀就能分清用途:

函数名后缀含义输入 → 输出适用场景
dumpss = StringPython 对象 → JSON 字符串日志打印、HTTP 请求参数构造
dump无后缀,写入 FilePython 对象 → 文件持久化配置、临时数据存储
loadss = StringJSON 字符串 → Python 对象解析 API 返回的字符串、日志中的 JSON 片段
load无后缀,读取 File文件 → Python 对象读取配置文件、本地 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.loadjson.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 模块的四核心函数。

pip install ujson
# 原代码只需修改导入,其余不动
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 常用命令速查表

命令作用
pip list查看当前环境已安装的所有库
pip install 库名安装指定库(默认最新版)
pip install 库名==x.y.z安装指定版本
pip install -U 库名更新库到最新版
pip uninstall 库名卸载指定库

5. 加餐二:实战调用公开 JSON API

如今绝大多数 API 都通过 HTTP/HTTPS 返回 JSON 数据。Python 内置的 urllib 使用起来比较繁琐,更推荐使用 requests 库——它被称为“最优雅的 HTTP 库”,内置 JSON 解析方法。

5.1 安装 requests

pip install 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 场景:

  1. JSON 的定位:跨语言、纯文本、结构紧凑的“数据桥接器”
  2. Python 内置 json 模块四大金刚dumps/dump(序列化)、loads/load(反序列化)
  3. 两个提效小工具
    • ujson:让大型 JSON 处理快如闪电
    • requests:优雅地调用 JSON API

最后提醒两个最容易出错的点:

  • 写 JSON 文件时 务必指定 encoding='utf-8',否则中文一定乱码。
  • JSON 的键必须是 双引号字符串。虽然 Python 的单引号键在序列化时会自动转换,但在手动拼写 JSON 字符串时,千万不要写出单引号

掌握这些,你就可以放心地在各种项目中使用 JSON 来存储、传输和交换数据了。