一个功能强大的 Python JSON 数据压缩工具,支持多种压缩算法和策略,可根据不同场景自动选择最优压缩方案。
- 🚀 多种压缩算法:Gzip、Zlib、Bz2、LZMA
- 🔑 智能键名压缩:自动缩短 JSON 键名
- 🎯 自动选择:根据数据大小和优先级自动选择最佳压缩方案
- 📊 压缩统计:详细的压缩率和性能对比
- 💾 Base64 编码:压缩结果可直接传输或存储
# 克隆仓库
git clone <repository-url>
cd json_compression
# 使用 uv 创建虚拟环境(如需要)
uv venv本工具仅使用 Python 标准库,无需额外安装依赖。
# 运行完整演示(包含所有压缩方法对比)
uv run .\json_compressor.py
# 仅运行自动压缩演示
uv run .\json_compressor.py --auto
# 显示帮助信息
uv run .\json_compressor.py --helpfrom json_compressor import JSONCompressor
# 示例数据
data = {
"user_id": 12345,
"username": "张三",
"items": [1, 2, 3, 4, 5]
}
# 快速压缩(推荐 Zlib,速度快,压缩率好)
compressed = JSONCompressor.compress_with_zlib(data)
print(f"压缩后: {len(compressed)} 字节")
# 解压
original = JSONCompressor.decompress_zlib(compressed)
print(f"解压验证: {original == data}")
# 自动选择最佳压缩方法
result = JSONCompressor.compress_auto(data, priority='ratio')
original = JSONCompressor.decompress_advanced(result)压缩率 = (1 - 压缩后大小 / 原始大小) × 100%
示例:
- 原始大小:482 字节
- 压缩后大小:428 字节
- 压缩率 = (1 - 428/482) × 100% = 11.20%
节省字节数 = 原始大小 - 压缩后大小
说明:
- 压缩率为正数表示数据被成功压缩,数值越大压缩效果越好
- 压缩率为负数表示压缩后体积反而增大(常见于极小数据或已压缩数据)
在对比表格中,相对格式化 JSON 的压缩率计算:
相对压缩率 = (1 - 当前大小 / 格式化JSON大小) × 100%
示例(基于运行结果):
- 格式化 JSON:646 字节
- Zlib 压缩:428 字节
- 相对压缩率 = (1 - 428/646) × 100% = 33.7%
原理:
- 去除 JSON 中的所有空格、换行符、缩进
- 不进行任何实际压缩,仅删除无用字符
- 完全可逆,不损失任何数据
特点:
- ✅ 速度极快(几乎无开销)
- ✅ 保持 JSON 可读性(可直接解析)
- ✅ 无需解压步骤
⚠️ 压缩率有限(通常 20-30%)
适用场景:
- API 响应优化
- 前端传输
- 需要保持 JSON 格式的场景
典型压缩率: 20-30%
原理:
- 基于 DEFLATE 算法(LZ77 + Huffman 编码)
- LZ77:查找重复字符串,用指针替换(距离+长度)
- Huffman 编码:高频字符用短编码,低频字符用长编码
- 包含 CRC32 校验和文件头
技术细节:
- 滑动窗口搜索重复模式(默认 32KB 窗口)
- 用 (距离, 长度) 对替换重复数据
- 对结果进行 Huffman 编码
特点:
- ✅ HTTP 标准压缩格式(浏览器原生支持)
- ✅ 速度与压缩率平衡良好
- ✅ 广泛应用于 Web 传输
⚠️ 额外的文件头开销(~18 字节)
适用场景:
- HTTP 响应压缩(Content-Encoding: gzip)
- Web API 数据传输
- 实时数据流
典型压缩率: 30-40%(小数据),70-90%(大数据)
原理:
- 同样基于 DEFLATE 算法
- 比 Gzip 更简洁的封装格式(2 字节头 + 4 字节校验)
- 使用 Adler-32 校验(比 CRC32 更快)
与 Gzip 的区别:
- 文件头更小(2 字节 vs 10 字节)
- 校验和算法不同(Adler-32 vs CRC32)
- 压缩核心算法完全相同
特点:
- ✅ 速度最快(三者中)
- ✅ 开销更小
- ✅ 内存占用少
- ✅ Python 标准库支持
适用场景:
- 通用数据压缩
- 实时传输(游戏、聊天)
- 内存受限环境
- 推荐作为默认选择
典型压缩率: 30-40%(小数据),70-90%(大数据)
性能对比(Zlib vs Gzip):
- 压缩速度:Zlib 快 5-10%
- 压缩率:基本相同(差异 < 1%)
- 解压速度:Zlib 快 5-15%
原理:
- 基于 Burrows-Wheeler 变换 (BWT) + RLE + Huffman 编码
- BWT:将相似字符聚集在一起(可逆排序变换)
- RLE:压缩连续重复字符
- Huffman:熵编码
技术流程:
- Burrows-Wheeler 变换(重排数据使相似字符相邻)
- Move-to-Front 变换(减小字符编码值)
- Run-Length 编码(压缩连续字符)
- Huffman 编码(熵编码)
特点:
- ✅ 高压缩率(比 Gzip/Zlib 高 15-30%)
- ✅ 对大数据效果显著
⚠️ 速度较慢(比 Zlib 慢 3-5 倍)⚠️ 内存占用较高(块大小通常 100-900KB)⚠️ 小数据可能负优化(< 1KB 时压缩率可能为负)
适用场景:
- 大文件压缩
- 数据归档
- 对速度要求不高但需要高压缩率的场景
- 离线批处理
典型压缩率: 10-30%(小数据),85-95%(大数据)
原理:
- 基于 Lempel-Ziv-Markov chain Algorithm
- 使用超大字典(可达数 MB)
- 结合 LZ77 + 范围编码(Range Encoding)
- 高度优化的匹配查找算法
技术特点:
- 巨大的滑动窗口(默认 8MB,可达 1.5GB)
- 复杂的匹配查找(多种匹配模式)
- 上下文相关的范围编码
- 多线程支持(在大数据时)
特点:
- ✅ 最高压缩率(通常比 Bz2 再高 10-20%)
- ✅ 对大数据集效果极佳
⚠️ 速度最慢(比 Zlib 慢 5-10 倍)⚠️ 内存占用大(压缩时可能需要数十 MB)⚠️ 小数据开销大(文件头等元数据占比高)
适用场景:
- 长期存储归档
- 文件分发(软件安装包)
- 数据备份
- 对压缩率要求极高的场景
典型压缩率: -10% 到 20%(小数据),90-99%(大数据)
原理:
- 将 JSON 中的长键名映射为短键名
- 自动生成映射表:
a,b,c, ...,z,A,B, ...,aa,ab, ... - 保存映射表用于解压恢复
示例:
原始数据:
{
"user_information": {"first_name": "张三"},
"order_details": [{"order_id": "001"}]
}压缩后:
{
"a": {"b": "张三"},
"c": [{"d": "001"}]
}映射表:
{
"a": "user_information",
"b": "first_name",
"c": "order_details",
"d": "order_id"
}特点:
- ✅ 对重复结构数据效果显著
- ✅ 可与其他压缩算法组合
- ✅ 减少数据冗余
⚠️ 需要传输映射表(增加开销)⚠️ 小数据或键名本身很短时效果不明显
适用场景:
- 大量相同结构的 JSON 对象(如数组记录)
- 键名很长的数据
- 与 LZMA/Bz2 组合使用
典型压缩率: 40-60%(独立使用),配合 LZMA 可达 99%
原理:
- 先进行键名压缩,减少重复键名
- 再用 LZMA 压缩已优化的数据
- 两阶段压缩互补增强
特点:
- ✅ 最高压缩率(大数据集可达 99%)
- ✅ 适合重复结构的大数据
⚠️ 速度最慢⚠️ 解压需要两步(先解压 LZMA,再还原键名)⚠️ 小数据开销大(映射表 + LZMA 头 > 节省量)
适用场景:
- 大量重复结构数据的长期存储
- 数据归档
- 需要极致压缩率的场景
典型压缩率: 90-99%(大数据),可能为负(小数据)
Minify > Zlib ≈ Gzip > Bz2 > LZMA
相对速度:
- Minify:基准(几乎无开销)
- Zlib:1.0x(推荐基准)
- Gzip:0.9x(比 Zlib 慢 ~10%)
- Bz2:0.3x(比 Zlib 慢 3-5 倍)
- LZMA:0.1-0.2x(比 Zlib 慢 5-10 倍)
小数据(< 1KB):
Minify (25%) > Zlib/Gzip (30-40%) > 键名压缩 (40-50%) > Bz2/LZMA(可能负优化)
中等数据(1KB - 100KB):
LZMA (70-85%) > Bz2 (65-80%) > Zlib/Gzip (60-75%) > 键名压缩 (50-60%)
大数据(> 100KB):
LZMA+键名 (95-99%) > LZMA (90-98%) > Bz2 (85-95%) > Zlib/Gzip (75-90%)
| 方法 | 内存占用 | 说明 |
|---|---|---|
| Minify | 极小 | 仅需原数据 1 份拷贝 |
| Zlib/Gzip | 小 | ~256KB + 数据大小 |
| Bz2 | 中等 | ~8MB(块大小 × 5) |
| LZMA | 大 | ~64MB+(字典大小相关) |
| 键名压缩 | 小 | 需存储映射表 |
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| HTTP API 传输 | Zlib 或 Gzip | 速度快,浏览器原生支持 |
| 实时通信 | Zlib | 最快,开销最小 |
| 数据存储 | LZMA 或 Bz2 | 最高压缩率,节省存储空间 |
| 大数据归档 | LZMA + 键名 | 极致压缩率 |
| 前端可见 | Minify | 保持可读性,无需解压 |
| 微服务间通信 | Zlib | 低延迟,CPU 开销小 |
| 日志归档 | Bz2 或 LZMA | 高压缩率,读取频率低 |
| 移动端传输 | Zlib | 省电,速度快 |
| 数据大小 | 推荐方法 | 备选 |
|---|---|---|
| < 100 字节 | Minify | 不压缩(开销大于收益) |
| 100B - 1KB | Zlib | Minify |
| 1KB - 10KB | Zlib | Gzip, Bz2 |
| 10KB - 100KB | Zlib 或 Bz2 | LZMA(压缩率优先) |
| > 100KB | LZMA + 键名 | Bz2 |
速度优先(Speed Priority):
# 实时系统、高并发场景
result = JSONCompressor.compress_auto(data, priority='speed')
# 自动选择:Zlib(所有数据大小)平衡模式(Balanced):
# 通用场景
result = JSONCompressor.compress_auto(data, priority='balanced')
# 自动选择:
# - < 100KB: Zlib
# - > 100KB: Bz2压缩率优先(Ratio Priority):
# 存储、归档场景
result = JSONCompressor.compress_auto(data, priority='ratio')
# 自动选择:
# - < 10KB: Zlib
# - 10-50KB: Bz2
# - > 50KB: LZMA + 键名压缩使用 Zlib 压缩数据(推荐)。
参数:
data: 字典、列表或 JSON 字符串level: 压缩级别 (0-9),9 为最高
返回: Base64 编码的压缩数据
示例:
compressed = JSONCompressor.compress_with_zlib(data, level=6)解压 Zlib 数据。
参数:
compressed_data: Base64 编码的压缩数据
返回: 原始 Python 对象
使用 Gzip 压缩数据(HTTP 标准)。
使用 Bz2 压缩数据(高压缩率)。
使用 LZMA 压缩数据(最高压缩率)。
压缩 JSON 键名。
返回: (压缩后的数据, 键名映射表)
示例:
compressed_data, reverse_map = JSONCompressor.compress_keys(data)
# 保存 reverse_map 用于解压还原键名。
组合压缩策略。
参数:
compression_type:'gzip','zlib','bz2','lzma'compress_keys: 是否同时压缩键名
返回: 包含压缩数据和元信息的字典
示例:
result = JSONCompressor.compress_advanced(
data,
compression_type='lzma',
compress_keys=True
)
# 传输 result 字典解压高级压缩结果。
自动选择最佳压缩方法。
参数:
priority:'speed','balanced','ratio'compress_keys: 是否尝试键名压缩
返回: 自动选择的压缩结果
示例:
# 自动选择,压缩率优先
result = JSONCompressor.compress_auto(data, priority='ratio')
original = JSONCompressor.decompress_advanced(result)最小化 JSON(去除格式化)。
返回: 最小化的 JSON 字符串
获取压缩统计信息。
返回:
{
'original_size': 1000,
'compressed_size': 300,
'saved_bytes': 700,
'compression_ratio': '70.00%'
}基于提供的运行输出,以下是各方法的实际压缩效果:
| 方法 | 压缩后大小 | 压缩率 | 相对格式化 JSON |
|---|---|---|---|
| Gzip | 444 字节 | 7.88% | -31.3% |
| Zlib | 428 字节 | 11.20% | -33.7% |
| Bz2 | 492 字节 | -2.07% | -23.8% |
| LZMA | 504 字节 | -4.56% | -22.0% |
| 键名压缩 | 285 字节 | 40.87% | -55.9% |
| LZMA+键名 | 728 字节 | -51.04% | +12.7% |
分析:
- 小数据时,Zlib 表现最佳
- Bz2 和 LZMA 因文件头开销导致负优化
- 键名压缩单独使用效果最好
- LZMA+键名组合反而增大(开销过高)
| 方法 | 压缩后大小 | 压缩率 | 实际大小 |
|---|---|---|---|
| Minify | 271,653 字节 | 34.92% | 265.29 KB |
| Gzip | 13,428 字节 | 96.78% | 13.11 KB |
| Zlib | 13,412 字节 | 96.79% | 13.10 KB |
| Bz2 | 6,560 字节 | 98.43% | 6.41 KB |
| LZMA | 4,264 字节 | 98.98% | 4.16 KB |
| 键名压缩 | 195,647 字节 | 53.13% | 191.06 KB |
| LZMA+键名 | 3,856 字节 | 99.08% | 3.77 KB |
分析:
- 大数据时,LZMA 优势明显(最高压缩率)
- Bz2 性能也很好(98.43%)
- LZMA+键名组合达到 99.08% 的极致压缩率
- Gzip/Zlib 在大数据时压缩率也很高(96%+)
from json_compressor import JSONCompressor
from flask import Flask, jsonify, Response
app = Flask(__name__)
@app.route('/api/data')
def get_data():
data = get_large_dataset() # 获取大数据
# 使用 Zlib 压缩(速度快)
compressed = JSONCompressor.compress_with_zlib(data)
return Response(
compressed,
mimetype='application/json',
headers={'Content-Encoding': 'custom-zlib'}
)import json
from json_compressor import JSONCompressor
# 存储数据
def save_to_file(data, filename):
result = JSONCompressor.compress_advanced(
data,
compression_type='lzma',
compress_keys=True
)
with open(filename, 'w') as f:
json.dump(result, f)
# 读取数据
def load_from_file(filename):
with open(filename, 'r') as f:
compressed_result = json.load(f)
return JSONCompressor.decompress_advanced(compressed_result)def process_batch(records):
"""处理大批量记录"""
# 自动选择最佳压缩
result = JSONCompressor.compress_auto(
records,
priority='ratio' # 压缩率优先
)
print(f"原始大小: {result['data_size']} 字节")
print(f"压缩方法: {result['type']}")
print(f"键名压缩: {'是' if result['key_compressed'] else '否'}")
return result- Windows 11
- Python 3.x
- PowerShell
小数据(< 1KB):
- 推荐:Zlib 或键名压缩
- 避免:LZMA、Bz2(负优化)
中等数据(1KB - 100KB):
- 平衡:Zlib(速度优先)
- 压缩率:Bz2 或 LZMA
大数据(> 100KB):
- 最佳:LZMA + 键名压缩(99%+ 压缩率)
- 速度与压缩率平衡:Bz2
- 小数据慎用高级压缩:Bz2 和 LZMA 在小数据(< 1KB)时可能导致体积增大
- 传输键名映射表:使用键名压缩时,必须保存并传输映射表
- Base64 开销:所有压缩结果都经过 Base64 编码,增加约 33% 体积(但便于传输)
- 内存限制:LZMA 压缩大数据时可能占用大量内存
- CPU 使用:LZMA 和 Bz2 会占用更多 CPU 时间
A: 压缩算法需要存储元数据(文件头、字典、校验和等)。当数据很小时,这些开销可能超过压缩节省的空间。
解决方案:
- 小于 100 字节:建议仅使用 Minify
- 100-1000 字节:使用 Zlib
- 大于 1KB:可以考虑更高级的压缩
A: 两者使用相同的 DEFLATE 压缩算法,差异仅在于封装格式:
- Zlib:2 字节头 + 压缩数据 + 4 字节 Adler-32 校验
- Gzip:10 字节头 + 压缩数据 + 8 字节尾(CRC32 + 原始大小)
选择建议:
- HTTP 标准:Gzip
- 通用场景:Zlib(更快,开销更小)
A: 键名压缩适用于:
- 大量相同结构的对象(如数组记录)
- 键名很长的数据
- 配合 LZMA 用于极致压缩
不适用:
- 键名本身很短(如
id,name) - 小数据(映射表开销大)
A: 压缩级别(0-9)的权衡:
- 0:不压缩(仅封装)
- 1-3:低压缩,快速
- 6:默认平衡点(推荐)
- 9:最高压缩,较慢
建议:
- 实时传输:Level 3-6
- 存储归档:Level 9
欢迎提交 Issue 和 Pull Request!
MIT License
最后更新: 2024-11-06