当前位置: 首页 > 科技观察

啃论文社---JSON压缩算法解读

时间:2023-03-13 19:21:12 科技观察

了解更多开源请访问:开源基础软件社区https://ost.51cto.comJSON压缩算法解读下一篇,我们将进入关于JSON压缩算法的学习。为什么需要压缩JSON?尽管JSON数据格式比XML更高效,但对于Web服务器和浏览器之间的传输而言,它仍然是一种相对低效的数据格式。为什么?首先,它将所有内容都转换为文本,其次,转换后的文本被过度引用,这会向每个字符串添加两个额外的字节。第三,它没有模式本身的标准格式。例如,序列化消息中的多个对象时,即使每个对象的属性的键名重复且相同,转换后的文本数据仍然会重复每个键名。JSON曾经有一个优势,就是可以直接被Javascript引擎解析,但是现在越来越重视安全,JSON的这个优势逐渐消失了,但是因为它比XML更高效,性能更好,很多传统的C/S模式大多选择JSON,比如webservices。当有大量的数据和复杂的数据结构需要从浏览器传输到服务器时,JSON压缩就起到了非常重要的作用,但是在这中间它会出现我们刚才提到的三个问题,我们不能使用传统的gzip压缩算法,因为浏览器不知道服务器是否支持gzip解压。我们来看看两种常见的JSON压缩算法,cJSON和HPack。cJSON压缩算法(cJSONCompressionAlgorithm)的特点是cJSON压缩算法可以使用自动类型提取来压缩JSON数据格式的内容。它成功解决了一个很重要的问题,也就是我们上一节提到的第三点,丢弃重复的键名。我们来看一个例子:使用cJSON之前的数据格式:[{//表示一个坐标点"x":100,"y":100},{//表示一个矩形"x":100,"y":100,"width":200,"height":150},{},//表示一个空对象...//下面省略几万个对象]在上面的未压缩数据中,我们可以看到有一个大量重复的键名占用空间,比如“x”、“y”等,当数据量很大时,这些看似不起眼的重复键名会对传输效率产生很大的影响。其实解决方法很简单,因为它们是重复的,那我们就存储一次不就好了吗?我们来看看cJSON按照我们的思路处理后的数据。{"templates":[["x","y"],//type1["x","y","width","height"]//type2],"value":[{//the第一个对象:坐标点"type":1,"values":[100,100]},{//第二个对象:矩形"type":2,"values":[100,100,200,150]},{//第三个空对象},//以下省略数万个对象...]}从上面的数据可以看出,我们已经格式化了数据,把键名存储起来了,而不存重复,然后value通过“type”索引对应键名,在数据量巨大的时候确实减少了很多空间,但是我们仔细看“templates”中的键名有仍然存在重复字段。说明我们还有优化的空间。优化压缩后效果如下:{"function":"cjson","templates":[[0,"x","y"],[1,"width","height"]],"values":[[1,100,100],//第一个对象:坐标点[2,100,100,200,150],//第二个对象:矩形[]//第三个空对象]}如果你直接看压缩后的代码结构,你可能看不懂,那我们就来看看它的具体原理吧。为了解决“模板”中键名重复的字段,本算法采用树的数据结构,每遇到一个要传输的对象,就将键值按顺序存储在树的节点中(灰色节点)是标记的结束节点指针,表示该节点存储了一个对象值的最后一个属性的key),重复的不会存储,解决了我们的问题。这个键值树的变化过程是这样的:当数据匹配到键值时,根据“values”数组中标记的结束节点指针找到对应的键值,这就构成了cJSON的压缩算法。细心的同学会发现,如果一个对象中没有“X”和“Y”,只有“width”和“height”,或者key-value节点的顺序不对,会不会有问题?答案是对的,会出现键值不匹配的情况,所以这种方式只能在特定的场景下应用,有一定的局限性。总的来说,cJSON在处理非常大量的数据时是非常客观的。JSON.HPack压缩算法(HPackCompressionAlgorithm)JSON.HPack是一种无损、跨语言、性能导向的JSON数据压缩算法,它允许我们使用post请求将数据从客户端发送到服务器。节省大约70%的字符。原理是和cJSON一样提取key和value。例如:在使用HPack算法之前:{"id":1,"sex":"Female","age":38,"classOfWorker":"Private","maritalStatus":"Married-civilianspousepresent","education":"1st2nd3rdor4thgrade","race":"White"}使用HPack算法后:["id","sex","age","classOfWorker","maritalStatus","education","race"],[1,"Female",38,"Private","Married-civilspousepresent","1st2nd3rdor4thgrade","White"]可以看到和普通JSON对比而cJSON,少了很多字符,比如引号,各种括号等等,这种压缩算法在数据量很大的情况下也很有效。HPack算法提供了多个压缩级别(从0到4)。等级越高,压缩效率越高,每一级都会引入额外的功能。0级压缩通过将键值与结构分离并在索引0处的元素上创建一个键名称数组来执行最基本的压缩。下一级可以通过假设存在重复条目来进一步减小JSON数据的大小。性能分析接下来我们就直接用数据来看一下这些压缩算法的压缩效率。我们使用5组不同大小(50KB~1MB)的JSON文件,每个JSON文件都会使用servlet容器(tomcat)提供给浏览器,并使用以下算法进行压缩:原始JSON大小-未修改的JSON数据。最小化——去除空格和换行(最基本的js优化)。CompressecJSON-使用CJSON压缩算法的JSON压缩.CompresseHPack-使用JSON.HPack压缩算法进行JSON压缩.Gzipped-使用gzip和JSON压缩。Gzipped+Minimized-使用gzip并删除空格和换行符的JSON压缩(最基本的js优化)。Gzipped+CompressecJSON-使用gzip和CJSON压缩算法进行JSON压缩。Gzipped+CompresseHPack-使用gzip和JSON.HPack压缩算法进行JSON压缩。下图(TABLEI.RESULTS)显示了上述方法处理的JSON数据的大小(字节)。不同的列代表不同的JSON数据集,不同的行代表不同的压缩方式。下面第一张图的Y轴代表JSON数据大小(字节):第二张图的Y轴是JSON数据大小的百分比(%),原始数据为100%:我们可以直观的看到从上面的图表来看,单独使用cJSON可以将原始数据大小压缩到45%左右,单独使用HPack可以将原始数据大小压缩到8%左右。可以看出HPack在整体上优于cJSON。但是我们可以看到,当使用gzip结合上述两种压缩算法进行JSON压缩时,效果是最优的,压缩率基本可以达到1%~2%。总的来说,HPack比cJSON效率更高、速度更快,但是在使用压缩算法进行传输的过程中,接收端需要进行相应的解压操作,否则压缩后的JSON数据无法使用,这也是会有一个一步有一定的性能开销,这也是我们选择使用JSON压缩时需要考虑的。当可以使用gzip进行压缩时,这种方式比其他压缩算法效率更高,两者同时结合使用时,效果明显。好了,这次我们对JSON序列化的发展、规范、应用及相关压缩算法有了一个完整的了解。相信大家不仅对JSON压缩算法有了更深的了解,对JSON序列化这个技术领域也有了深刻的了解。知道。文章相关附件可点击下方原文链接下载:https://ost.51cto.com/resource/2290。了解更多开源知识,请访问:开源基础软件社区https://ost.51cto.com。