json压缩与解压

news/2025/12/3 17:41:00/文章来源:https://www.cnblogs.com/ciel717/p/17646778.html

一、概述

在现代应用开发中,JSONJavaScript Object Notation)作为一种轻量级的数据交换格式被广泛使用。然而,在网络传输或者数据存储的过程中,如何有效地压缩和解压JSON数据,是很多开发者需要解决的问题。

部分数据如下所示:

{"33828": {"code": "33828","name": "萤","order": "7298","strokeSum": "11"},"22920": {"code": "22920","name": "妈","order": "1051","strokeSum": "6"},"20718": {"code": "20718","name": "僮","order": "13341","strokeSum": "14"},"30615": {"code": "30615","name": "瞗","order": "15845","strokeSum": "16"},"36969": {"code": "36969","name": "適","order": "13506","strokeSum": "14"}
}

二、常规压缩json

2.1 去除冗余字符(单行压缩)

将JSON压缩成一行,去掉换行和空格字符后的json文件大小为:1.39Mb,只之前的2.13Mb小了整整0.74Mb,这个在移动端是很可观的优化!

2.2 缩短键名(减少重复冗余)

jsonkey-value结构,如果定义好规范,则可以将key尽量缩短,甚至是无意义的字母,但前提是文档一定要写清楚,避免不必要的麻烦。

比如之前的key-value结构如下所示:

{"33828": {"code": "33828","name": "萤","order": "7298","strokeSum": "11"},"22920": {"code": "22920","name": "妈","order": "1051","strokeSum": "6"},"20718": {"code": "20718","name": "僮","order": "13341","strokeSum": "14"},"30615": {"code": "30615","name": "瞗","order": "15845","strokeSum": "16"},"36969": {"code": "36969","name": "適","order": "13506","strokeSum": "14"}
}

现在我们将key进行优化,使用

c 代替 code
n 代替 name
o 代替 order
s 代替 strokeSum

将JSON的key进行缩短优化后的json文件大小为:1.77Mb,只之前的2.13Mb小了整整0.36Mb,这个在移动端是很可观的优化!

然后再将缩短key之后的文件,压缩成一行,去掉换行和空格字符。再看一看文件大小为1.04Mb,比最开始的原始数据2.13Mb小了整整1.09Mb!

当然这样key的名字变化了,对应解析Json的java实体bean也要修改一下。

因为我使用的是jackson来进行json解析的,所以使用注解@JsonProperty来表示一下修改的json文件对应原来的java bean里面的属性,这样解析的时候就不会出错了。

2.3 常规总结

经过上面的常规操作,我们的json文件大小减少到了1.04Mb,比最开始的原始数据2.13Mb,小了整整1.09Mb,

压缩率为51.174%,压缩后体积为原来的48.826%

已经算很给力了,但是这个json文件还是有1.04Mb啊,是否还可以进行压缩呢?答案是肯定的。

三、常用压缩算法

3.1 Deflater与Inflater

Deflater是同时使用了LZ77算法与哈夫曼编码的一个无损数据压缩算法。

我们可以使用java提供的DeflaterInflater类对json进行压缩和解压缩,下面是工具类

import android.support.annotation.Nullable;
import android.util.Base64;import java.io.ByteArrayOutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;/*** DeflaterUtils 压缩字符串*/
public class DeflaterUtils {/*** 压缩* * Deflater 压缩等级:0 ~ 9 压缩等级 低到高* public static final int BEST_COMPRESSION = 9;     最佳压缩的压缩级别。* public static final int BEST_SPEED = 1;           压缩级别最快的压缩。* public static final int DEFAULT_COMPRESSION = -1; 默认压缩级别。* public static final int DEFAULT_STRATEGY = 0;     默认压缩策略。* public static final int DEFLATED = 8;             压缩算法的压缩方法(目前唯一支持的压缩方法)。* public static final int FILTERED = 1;             压缩策略最适用于大部分数值较小且数据分布随机分布的数据。* public static final int FULL_FLUSH = 3;           压缩刷新模式,用于清除所有待处理的输出并重置拆卸器。* public static final int HUFFMAN_ONLY = 2;         仅用于霍夫曼编码的压缩策略。* public static final int NO_COMPRESSION = 0;       不压缩的压缩级别。* public static final int NO_FLUSH = 0;             用于实现最佳压缩结果的压缩刷新模式。* public static final int SYNC_FLUSH = 2;  用于清除所有未决输出的压缩刷新模式;可能会降低某些压缩算法的压缩率。*/public static String zipString(String unzipString) {//使用指定的压缩级别创建一个新的压缩器。Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);//设置压缩输入数据。deflater.setInput(unzipString.getBytes());//当被调用时,表示压缩应该以输入缓冲区的当前内容结束。deflater.finish();final byte[] bytes = new byte[256];ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);while (!deflater.finished()) {//压缩输入数据并用压缩数据填充指定的缓冲区。int length = deflater.deflate(bytes);if (length == 0) {break;}outputStream.write(bytes, 0, length);}try {outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}//关闭压缩器并丢弃任何未处理的输入。deflater.end();return Base64.encodeToString(outputStream.toByteArray(), Base64.NO_PADDING);}/*** 解压缩*/@Nullablepublic static String unzipString(String zipString) {byte[] decode = Base64.decode(zipString, Base64.NO_PADDING);//创建一个新的解压缩器Inflater inflater = new Inflater();//设置解压缩的输入数据。inflater.setInput(decode);final byte[] bytes = new byte[256];ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);try {//finished() 如果已到达压缩数据流的末尾,则返回true。while (!inflater.finished()) {//将字节解压缩到指定的缓冲区中。int length = inflater.inflate(bytes);outputStream.write(bytes, 0, length);}} catch (DataFormatException e) {e.printStackTrace();return null;} finally {//关闭解压缩器并丢弃任何未处理的输入。inflater.end();}return outputStream.toString();}
}

3.1.1 压缩json

然后我们先将原始的stroke.json数据压缩成deFlaterStrokeJson.json

//原始文件   stroke.json
String strokeJson = LocalFileUtils.getStringFormAsset(context, "stroke.json");
mapper = JSONUtil.toCollection(strokeJson, HashMap.class, String.class, Stroke.class);
// 使用 Deflater  加密
String deFlaterStrokeJson = DeflaterUtils.zipString(strokeJson);
writeFile(deFlaterStrokeJson,"deFlaterStrokeJson.json");

其中writeFile方法是写入到sdcard的方法。

private static void writeFile(String mapperJson, String fileName) {Writer write = null;try {File file = new File(Environment.getExternalStorageDirectory(), fileName);Log.d(TAG, "file.exists():" + file.exists() + " file.getAbsolutePath():" + file.getAbsolutePath());// 如果父目录不存在,创建父目录if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}// 如果已存在,删除旧文件if (file.exists()) {file.delete();}file.createNewFile();// 将格式化后的字符串写入文件write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");write.write(mapperJson);write.flush();write.close();} catch (Exception e) {Log.e(TAG, "e = " + Log.getStackTraceString(e));} finally {if (write != null){try {write.close();} catch (IOException e) {Log.e(TAG, "e = " + Log.getStackTraceString(e));}}}
}

运行完毕之后,将sdcard中的deFlaterStrokeJson.json导出来,放到assets目录下,以备后续解析使用。

使用Deflater压缩json,压缩后大小为 387KB,比上一次的1067KB,又少了很多很多。

经过Deflater压缩和Base64编码之后的deFlaterStrokeJson.json文件,如下所示:

3.1.2 解压json

关压缩还不行,我们得使用压缩后的json文件数据啊,因此我们还需要将压缩后的json数据进行解压,操作如下所示:

//使用 Inflater 解密
String deFlaterStrokeJson = LocalFileUtils.getStringFormAsset(context, "deFlaterStrokeJson.json");
String strokeJson = DeflaterUtils.unzipString(deFlaterStrokeJson);
mapper = JSONUtil.toCollection(strokeJson, HashMap.class, String.class, Stroke.class);

解压之后运行一切正常!完美!

3.1.3 小结

经过上面的常规操作,我们的json文件大小减少到了387KB,比刚才未使用压缩算法的原始数据1067KB,小了整整680KB,

压缩率为63.73%,压缩后体积为原来的36.27%

优化步骤 体积
1.未处理的原始json 2.13MB
2.将JSON压缩成一行,去掉换行和空格字符 1.39MB
3.将JSON的key进行缩短 1.04MB
4.使用Deflater压缩json,Base64编码 0.38MB

3.2 Gzip

在我封装的http库里面,有对请求json数据进行Gzip压缩,对服务器返回的json数据进行Gzip解压。这里也来试一下Gzip压缩json

编写一个Gzip压缩解压并使用Base64进行编码工具类

import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;/*** Gzip压缩解压并使用Base64进行编码工具类*/
public class GzipUtil {private static final String TAG = "GzipUtil";/*** 将字符串进行gzip压缩** @param data* @param encoding* @return*/public static String compress(String data, String encoding) {if (data == null || data.length() == 0) {return null;}ByteArrayOutputStream out = new ByteArrayOutputStream();GZIPOutputStream gzip;try {gzip = new GZIPOutputStream(out);gzip.write(data.getBytes(encoding));gzip.close();} catch (IOException e) {e.printStackTrace();}return Base64.encodeToString(out.toByteArray(), Base64.NO_PADDING);}public static String uncompress(String data, String encoding) {if (TextUtils.isEmpty(data)) {return null;}byte[] decode = Base64.decode(data, Base64.NO_PADDING);ByteArrayOutputStream out = new ByteArrayOutputStream();ByteArrayInputStream in = new ByteArrayInputStream(decode);GZIPInputStream gzipStream = null;try {gzipStream = new GZIPInputStream(in);byte[] buffer = new byte[256];int n;while ((n = gzipStream.read(buffer)) >= 0) {out.write(buffer, 0, n);}} catch (IOException e) {Log.e(TAG, "e = " + Log.getStackTraceString(e));} finally {try {out.close();if (gzipStream != null) {gzipStream.close();}} catch (IOException e) {Log.e(TAG, "e = " + Log.getStackTraceString(e));}}return new String(out.toByteArray(), Charset.forName(encoding));}
}

3.2.1 压缩json

//原始文件   stroke.json
String strokeJson = LocalFileUtils.getStringFormAsset(context, "stroke.json");
mapper = JSONUtil.toCollection(strokeJson, HashMap.class, String.class, Stroke.class);
// 使用 GZIP  压缩
String gzipStrokeJson = GzipUtil.compress(strokeJson,CHARSET_NAME);
writeFile(gzipStrokeJson,"gzipStrokeJson.json");

运行完毕之后,将sdcard中的gzipStrokeJson.json导出来,放到assets目录下,以备后续解析使用。

导出来的gzipStrokeJson.json文件为405kb,没有比刚才使用Deflater压缩json后大小为387KB优秀!

3.2.2 解压json

关压缩还不行,我们得使用压缩后的json文件数据啊,因此我们还需要将压缩后的json数据进行解压,操作如下所示:

//使用 GZIP 解压
String gzipStrokeJson = LocalFileUtils.getStringFormAsset(context, "gzipStrokeJson.json");
String strokeJson = GzipUtil.uncompress(gzipStrokeJson,CHARSET_NAME);
mapper = JSONUtil.toCollection(strokeJson, HashMap.class, String.class, Stroke.class);

解压之后,json解析一切正常!

3.2.3 小结

经过上面的常规操作,我们的json文件大小减少到了405kb,虽然比不上刚才的Deflater压缩:387KB,但是比刚才未使用压缩算法的原始数据1067KB,小了整整662KB,

压缩率为62.04%,压缩后体积为原来的37.95%,也是不错的!

四、 其他压缩算法

除了上面的算法之外,我们还可以使用很多其他的压缩算法,进一步压缩json的体积。我们的原始json中还是有很多重复的key值可以进行优化的,下面的算法中有部分可以进行key优化!

常见的json压缩算法有CJSON与HPack,其原理都是将key和value进行抽离,节省掉部分的重复的key值造成的空间消耗。

4.1 CJSON

CJSON的压缩算法,主要是将资料抽离成Template与Value,节省掉重复的"Key值".

原始JSON:

[{"x": 100,"y": 100
}, {"x": 100,"y": 100,"width": 200,"height": 150
}, {}]

CJSON压缩后:

{"templates": [[0, "x", "y"],[1, "width", "height"]],"values": [{"values": [1, 100, 100]}, {"values": [2, 100, 100, 200, 150]}, {}]
}

4.2 HPack

HPack的压缩算法,也是将Key, Value抽离,阵列中第一个值,就是HPack的Template,后面依序就是Value。

[{"name": "Andrea","age": 31,"gender": "Male","skilled": true
}, {"name": "Eva","age": 27,"gender": "Female","skilled": true
}, {"name": "Daniele","age": 26,"gender": "Male","skilled": false
}]

压缩之后的数据

[["name", "age", "gender", "skilled"],["Andrea", 31, "Male", true],["Eva", 27, "Female", true],["Daniele", 26, "Male", false]
]

两种方法都是主要讲json的键抽出来统一建成索引,只是最后的格式不同。

HPack简化后的格式比CJSON少了许多字符,所以HPack的压缩效率比较高。数据量越大,效果越明显,应用场景也更加有意义。

如果JSON内容太少,CJSON的资料可能反而会比较多。

更多参考:https://www.oschina.net/p/jsonhpack

五、JSON的替代品

虽然JSON是一种通用的数据交换格式,但由于其在某些情况下的性能限制,开发者开始探索更快的替代格式。我们来看以下其中的一些替代方案。

5.1 协议缓冲区(protobuf)

协议缓冲区(通常称为protobuf)是谷歌开发的一种二进制序列化格式。其设计宗旨是高效、紧凑和快速。Protobuf的二进制特性使其在序列化和反序列化时比JSON快得多。

何时使用:当你需要高性能数据交换时,尤其是在微服务架构、物联网应用或网络带宽有限的情况下,请考虑使用 protobuf。

5.2 MessagePack信息包

MessagePack是另一种二进制序列化格式,以速度快、结构紧凑而著称。其设计目的是在保持与各种编程语言兼容的同时,提高比JSON更高的效率。

何时使用:当你需要在速度和跨语言兼容性之间取得平衡时,MessagePack是一个不错的选择。它适用于实时应用程序和对减少数据量有重要要求的情况。

5.3 BSON(二进制JSON)

BSON或二进制JSON是一种从JSON衍生出来的二进制编码格式。它保留了JSON的灵活性,同时通过二进制编码提高了性能。BSON常用于MongoDB等数据库。

何时使用:如果你正在使用MongoDB,或者需要一种能在JSON和二进制效率之间架起桥梁的格式,那么BSON就是一个很有价值的选择。

5.4 Apache Avro

Apache Avro是一个数据序列化框架,专注于提供一种紧凑的二进制格式。它基于模式,可实现高效的数据编码和解码。

何时使用Avro适用于模式演进非常重要的情况,如数据存储,以及需要在速度和数据结构灵活性之间取得平衡的情况。

JSON相比,这些替代方案在性能上有不同程度的提升,具体选择取决于您的具体使用情况。通过考虑这些替代方案,您可以优化应用程序的数据交换流程,确保将速度和效率放在开发工作的首位。

六、总结与推荐方案

  1. 基础优化优先:所有场景均建议先执行“键名缩短 + 单行压缩”,无额外开发成本却能缩减50%体积。
  2. 本地存储推荐:优先选择Deflater算法,以387KB的极致压缩率节省存储和本地读取时间。
  3. 网络传输推荐:优先选择Gzip算法,兼顾压缩率与兼容性,可直接与HTTP协议的Gzip压缩对接。
  4. 海量重复键名推荐:HPack算法,压缩效率最优,适合JSON数组类数据的大规模传输。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/985810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 美国留学机构 TOP10 推荐:精准适配需求,冲刺藤校更有底气

美国留学申请早已进入 “个性化竞争” 时代 —— 藤校及 TOP30 院校不仅看重 GPA 与标化成绩,更关注文书叙事、背景独特性与院校适配度。不同学子或冲刺顶尖名校,或需低背景逆袭,或专攻艺术细分领域,对机构的服务需…

2025年特氟龙喷涂厂家权威推荐榜单:无机纤维喷涂/静电喷涂/不锈钢喷塑加工源头厂家精选

在高端制造业、食品加工、医疗器械、化工防腐等领域,特氟龙(PTFE)涂层以其卓越的不粘性、优异的耐化学腐蚀性、宽广的工作温度范围和出色的电绝缘性,成为众多精密零部件表面处理的核心选择。随着环保标准日益严格和…

2025最新招投标系统实战推荐TOP5:从全流程数智化到垂直场景适配,企业选型指南

在招投标数字化深化的当下,系统的 “全流程覆盖能力、合规安全性、场景适配度” 成为企业选型核心标尺。基于《电子招标投标系统技术规范》要求及 300 余家企业实测反馈,以下 5 家招投标系统服务商凭借差异化优势脱颖…

2025年12月出入口安防系统,安防监控系统,弱电安防系统厂家推荐:聚焦安防核心需求,资质认证与案例落地双保障!

2025年12月出入口安防系统、安防监控系统、弱电安防系统厂家推荐在2025年,随着社会对安全和智能化需求的不断提升,出入口安防系统、安防监控系统以及弱电安防系统的重要性日益凸显。选择一家靠谱的厂家至关重要,北京…

专业的ERP系统推荐榜:聚焦企业信息化管理需求

在企业数字化转型进程中,ERP系统作为整合资源、优化流程的核心工具,对提升运营效率、实现管理升级具有重要意义。本文结合市场反馈与技术实力,整理出当前国内专业的ERP系统推荐榜单,为不同行业企业提供参考。一、推…

知名的ERP系统推荐:国内主流品牌及特点解析

ERP系统作为企业资源计划的核心工具,通过整合采购、生产、销售、财务等核心业务流程,帮助企业实现数据驱动决策、提升运营效率。随着数字化转型加速,国内涌现出众多技术成熟、适配性强的ERP系统品牌,以下结合市场反…

市面上符合香港标准防火卷帘门厂家口碑排行哪家好

在现代建筑安全体系中,防火卷帘门作为重要的消防分隔设施,其性能是否符合标准直接关系到建筑安全。香港地区对防火产品有着严格的技术规范,因此了解符合香港标准的防火卷帘门厂家口碑情况,对于相关领域从业者具有一…

专业的ERP系统推荐榜单:2025年国内主流方案解析

在企业数字化转型进程中,ERP系统作为整合资源、优化流程的核心工具,其选型质量直接影响管理效率与业务增长。本文基于技术成熟度、用户反馈及行业适配性,梳理国内专业ERP系统推荐榜单,为不同需求的企业提供参考。一…

膜电极外观缺陷检测设备:工业质检的高精度技术支撑

膜电极作为新能源、燃料电池等领域的核心组件,其外观质量直接影响产品性能与使用寿命。膜电极外观缺陷检测设备通过光学成像、图像分析等技术,可精准识别表面划痕、破损、杂质等缺陷,是保障生产一致性、提升产品合格…

知名的ERP系统排行:聚焦企业数字化转型优选方案

在当前企业数字化转型的浪潮中,ERP系统作为整合企业资源、优化业务流程的核心工具,其选择对于企业提升运营效率、实现数据驱动决策具有重要意义。本文结合市场反馈与技术实力,整理出一份知名的ERP系统推荐榜单,为不…

随着IT高效的技术和OT手艺发展的ISA-95体系演进过程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025知名的ERP系统排行榜单及实力企业推荐

在企业数字化转型进程中,ERP系统作为整合资源、优化流程的核心工具,其选择对企业发展至关重要。本文结合市场反馈与技术实力,整理出当前国内值得关注的ERP系统相关企业榜单,为行业用户提供参考。一、推荐榜单推荐 …

皮革外观缺陷检测设备:技术方案与应用领域探讨

皮革外观缺陷检测设备是皮革生产过程中保障产品质量的关键设备,通过光学成像、图像分析等技术,可快速识别皮革表面的划痕、色差、瑕疵等缺陷,助力企业提升生产效率与产品一致性。随着制造业智能化升级,此类设备在皮…

靠谱的AI公司有哪些?国内优质企业推荐

随着人工智能技术的快速发展,AI已深度融入千行百业,为产业升级提供核心动力。选择一家技术扎实、服务可靠的AI企业,成为众多机构和企业的重要需求。以下结合行业实践,推荐几家在技术研发与场景落地方面表现突出的国…

展厅设计施工一体化公司推荐:行业精选机构盘点

展厅设计施工一体化公司推荐:行业精选机构盘点在展厅建设领域,设计施工一体化模式正成为提升项目效率与质量的重要选择。这种模式通过统筹设计创意与施工执行环节,有效减少沟通成本,确保方案落地性,同时实现责任主…

钙钛矿外观缺陷检测设备:技术创新与应用解析

钙钛矿作为新一代光伏材料,凭借高效率、低成本的优势成为新能源领域的研究热点。在钙钛矿电池的生产过程中,外观缺陷如裂纹、针孔、杂质等会直接影响电池的光电转换效率与稳定性,因此高精度的外观缺陷检测设备成为保…

行业内符合欧标EI120防火卷帘门厂家排名一览

行业内符合欧标EI120防火卷帘门厂家排名一览欧标EI120防火卷帘门作为建筑消防系统中的关键组成部分,其防火性能、稳定性及合规性对建筑安全具有重要意义。在选择相关产品时,厂家的技术实力、认证资质及行业口碑是重要…

市面上符合香港标准防火卷帘门厂家排名哪家强

香港地区对建筑消防安全有着严格的标准要求,防火卷帘门作为建筑防火分隔的重要设施,其产品质量与性能需符合香港消防条例及相关规范。近年来,随着内地与香港建筑领域的合作深化,符合香港标准的防火卷帘门厂家受到市…

2025年泳池水过滤设备实力厂家权威推荐榜单:会所泳池‌/部队泳池‌/私人别墅泳池‌源头厂家精选

随着国民健康意识提升及休闲度假产业蓬勃发展,中国泳池市场规模持续扩大。游泳池水质安全是运营管理的核心,其中水过滤与循环系统作为保障水质的第一道防线,其重要性不言而喻。据行业市场分析,一个标准商业泳池的运…

有色金属外观缺陷检测设备的技术发展与应用现状

引言有色金属外观缺陷检测设备是工业生产中保障产品质量的关键工具,通过光学成像、图像处理等技术,可精准识别金属表面的划痕、凹陷、色差等缺陷,广泛应用于汽车制造、消费电子、新能源等领域,对提升生产效率和产品…