对象的序列化与反序列化

之前我们学会了把零散的文本、二进制存盘读取,但真实开发里哪有单独存「变量名」的场景? 比如要存一份AI训练的配置列表、和前端交互的用户数据,甚至跨语言(Python→Java→Go)的微服务通信——异构系统间必须用通用的、无损还原的「数据桥接器」,而JSON就是目前最火的那个。


1. JSON 是什么:从JS语法到全球“数据通行证”

JSON 的全称是 JavaScript Object Notation,最初确实只是 JS 里写对象的简化语法糖,但架不住它太“好用”:

  • 纯文本:随便用记事本打开、改
  • 结构紧凑:比冗长的XML少N多标签
  • 跨语言全支持:不管是前端、后端、移动端还是嵌入式,主流语言都有内置/成熟的解析库

如今它已经彻底取代 XML,成了API对接、配置文件的事实标准

JS ↔ Python 数据无缝映射表

JSON 的结构和 Python 字典/列表简直是「失散多年的孪生兄弟」,支持无限层嵌套,但为了跨语言兼容,它的数据类型比 Python 要少一些,对应关系如下:

表 1:JSON → Python 反序列化默认映射

JSON 类型Python 类型核心说明
objectdict键必须是双引号包裹的字符串
arraylist有序可变序列
stringstr统一Unicode编码,中文没问题
numberint / float自动区分整数和浮点数
booleanbooltrueTruefalseFalse(注意大小写!)
nullNonePython 里的空对象占位符

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

不用安装任何三方库!Python 自带的 json 模块,就能搞定 内存对象 ↔ JSON(字符串/文件) 的双向转换,核心就4个函数,记牢即可:

函数名后缀含义输入输出适用场景
dumpss=String对象 → JSON字符串日志打印、HTTP POST/GET参数
dump无后缀=File对象 → 本地/远程文件持久化配置、存储临时数据
loadss=StringJSON字符串 → 对象解析API返回的字符串、日志中的JSON
load无后缀=File本地/远程文件 → 对象读取配置文件、本地数据

实战演示:序列化“道满的业务配置”

我们用一个带嵌套结构、中文、布尔值、数组的复杂字典来练手:

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的Unicode编码
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!")

实战演示:反序列化还原配置

刚才我们存了配置,现在读回来验证:

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])

3. 加餐1:海量数据下的性能优化

处理 百万级以上的JSON数据(比如爬虫爬取的商品信息、AI批量推理的结果)时,Python 内置的 json 模块速度会有点慢——此时可以用Python生态里的「闪电解析器」ujson

第一步:pip 配置国内镜像(必做!否则下载慢死)

pip 是 Python 的官方包管理工具,默认从国外的 PyPI 下载,国内经常卡成狗。我们可以换成清华/阿里的镜像:

# 永久配置清华镜像(推荐)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

第二步:安装和使用 ujson

安装后,代码只需要改一行导入语句,完全兼容内置 json 的4个核心函数:

# 安装 ujson
pip install ujson
# 把 import json 改成 import ujson as json
import ujson as json  # 别名替换,其他代码一点不用动!

# 之前的 model_config 序列化/反序列化代码直接运行即可
# 速度通常比内置快 3-10 倍!

pip 常用命令速查

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

4. 加餐2:实战调用公开JSON API

现在99%的公开/商业网络API,都是基于 HTTP/HTTPS 协议返回JSON数据的。Python 内置的 urllib 有点繁琐,我们用第三方库requests(号称“最优雅的HTTP库”)来练手。

第一步:安装 requests

pip install requests

第二步:调用公开天气/新闻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)
    # 检查请求是否成功(200是HTTP成功状态码)
    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}")

5. 总结

今天我们只学了3件核心事,但足够应付90%的JSON场景:

  1. JSON的定位:全球通用的“数据桥接器”,跨语言、纯文本、紧凑
  2. Python内置json模块的4个函数dumps/dump(序列化)、loads/load(反序列化)
  3. 两个常用的小工具ujson(高性能)、requests(HTTP API对接)

最后再强调两个避坑点

  • 写JSON文件时必须指定encoding='utf-8',否则中文必乱码
  • JSON的键只能是双引号包裹的字符串,Python的单引号/整数键都会在序列化时自动转,但别在JSON字符串里写单引号!