目录
一、背景与核心价值
在现代数据开发中,JSON(JavaScript Object Notation) 已成为跨语言、跨平台数据交换的事实标准。相比于CSV或纯文本,JSON的优势在于:
- 结构化存储:天然支持嵌套字典、列表等复杂数据结构。
- 强可读性:键值对形式清晰描述数据含义,便于人工校验。
- 广泛兼容:Web API、NoSQL数据库(如MongoDB)、前后端通信均默认使用JSON。
本文目标:基于Python标准库json模块,深入解析JSON文件的序列化与反序列化技巧,解决日期、自定义对象等复杂数据类型的存储问题,并提供生产级代码模板与避坑指南。
二、JSON基础与核心应用场景
2.1 JSON数据结构规则
- 基本类型:字符串(“”)、数字、布尔值(true/false)、null、对象({})、数组([])。
- 语法限制:
- 键名必须用双引号包裹。
- 禁止末尾逗号(如{“a”:1,}无效)。
- 不支持注释(部分解析库可扩展支持)。
2.2 典型应用场景
场景 | 说明 |
---|---|
配置文件存储 | 程序参数、路径配置等(如config.json) |
API数据交互 | 前后端通过JSON格式传递请求与响应 |
结构化日志记录 | 记录带元数据的操作日志,便于后续分析 |
三、Python json模块核心操作
3.1 基础读写:dump()与load()
- 写入JSON文件:
import json
data = {
"project": "数据分析平台",
"version": 2.1,
"authors": ["张三", "李四"],
"tags": {"python": 5, "database": 3}
}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2) # 禁用ASCII转义,缩进2空格
生成文件data.json:
{
"project": "数据分析平台",
"version": 2.1,
"authors": ["张三", "李四"],
"tags": {
"python": 5,
"database": 3
}
}
- 读取JSON文件:
with open("data.json", "r", encoding="utf-8") as f:
loaded_data = json.load(f)
print(loaded_data["tags"]["python"]) # 输出:5
3.2 字符串与对象的转换:dumps()与loads()
- 对象转JSON字符串:
data_str = json.dumps(data, ensure_ascii=False)
print(type(data_str)) # <class 'str'>
- 字符串转Python对象:
json_str = '{"name": "王五", "age": 30}'
obj = json.loads(json_str)
print(obj["age"]) # 输出:30
四、处理复杂数据类型
4.1 日期时间对象
JSON默认不支持Python的datetime对象,需自定义转换逻辑:
from datetime import datetime
def datetime_encoder(obj):
if isinstance(obj, datetime):
return obj.isoformat() # 转为ISO格式字符串
raise TypeError("类型无法序列化")
data = {"event": "发布会", "time": datetime.now()}
# 序列化时指定自定义编码函数
json_str = json.dumps(data, default=datetime_encoder, ensure_ascii=False)
print(json_str) # {"event": "发布会", "time": "2024-07-20T15:30:45.123456"}
4.2 自定义类的序列化
若需存储自定义类实例,需实现__dict__方法或指定序列化函数:
class User:
def __init__(self, name, level):
self.name = name
self.level = level
user = User("赵六", 3)
# 方法1:手动转换字典
user_dict = {"name": user.name, "level": user.level}
json.dumps(user_dict)
# 方法2:使用__dict__(需类属性均为可序列化类型)
json.dumps(user.__dict__)
五、实战案例:配置文件管理与API数据存储
5.1 动态生成配置文件
import json
config = {
"database": {
"host": "localhost",
"port": 3306,
"user": "admin",
"password": "secret"
},
"logging": {
"level": "INFO",
"path": "/var/logs/app.log"
}
}
with open("config.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=4)
print("配置文件已生成!")
5.2 存储API返回的嵌套数据
import requests
import json
url = "https://api.example.com/books"
response = requests.get(url)
books_data = response.json() # 直接获取JSON对象
# 筛选评分大于4的书籍
filtered_books = [book for book in books_data if book["rating"] > 4]
with open("high_rating_books.json", "w", encoding="utf-8") as f:
json.dump(filtered_books, f, ensure_ascii=False, indent=2)
六、高级技巧与性能优化
6.1 控制序列化行为
- 跳过特定字段:
def filter_encoder(obj):
if "password" in obj:
del obj["password"]
return obj
user_data = {"name": "张三", "password": "123456"}
json.dumps(user_data, default=filter_encoder) # {"name": "张三"}
- 紧凑输出:取消缩进和空格
json.dumps(data, separators=(",", ":")) # 输出最简格式
6.2 使用第三方库加速
- ujson:C实现的超高速JSON库(API兼容)。
import ujson as json # 替换标准库
json.dumps(data) # 速度提升3-10倍
6.3 大文件分块读写
避免一次性加载大文件导致内存溢出:
# 逐行读取JSON数组文件(每行为独立JSON对象)
with open("large_data.json", "r", encoding="utf-8") as f:
for line in f:
item = json.loads(line)
process(item)
七、注意事项与总结
7.1 核心总结
- 基础能力:json模块提供了简单高效的序列化方案。
- 复杂场景:通过自定义编码函数处理日期、类实例等特殊类型。
- 性能优化:选择ujson或分块读写应对大数据量。
7.2 JSON的局限性
- 无注释支持:不适合需要备注的配置文件(可改用YAML)。
- 存储效率低:二进制格式(如MessagePack)更节省空间。