JSON编码数据包的压缩算法?

18

在将数据包发送到网络之前,选择什么样的压缩算法对于以JSON编码的数据包进行压缩最好?LZW是否适用于此类任务,还是有更好的选择?


我不知道具体的算法,但是也许这个项目对你有帮助:https://github.com/rgcl/jsonpack - Aditya Kresna Permana
7个回答

11

我认为有两个问题会影响你的答案:

1)在不知道程序每次运行会发生什么的情况下,你能多大程度地预测数据的组成?例如,如果你的数据包看起来像这样:

{
    "vector": {
        "latitude": 16,
        "longitude": 18,
        "altitude": 20
    },
    "vector": {
        "latitude": -8,
        "longitude": 13,
        "altitude": -5
    },
    [... et cetera ...]
}
-- 那么您可能会通过创建一个硬编码的文本字符串字典来获得最佳压缩效果,并将每个文本字符串的出现替换为相应的字典索引。(实际上,如果数据有规律,您可能只需要通过网络发送值,并在客户端编写一个函数从这些值构造 JSON 对象,如果需要的话。)
如果您无法预测将使用哪些标题,则可能需要使用 LZW、LZ77 或另一种方法,该方法查看已经通过的数据以找到可以用特别紧凑形式表达的数据。但是...
2) 数据包是否需要单独压缩?如果是,则 LZW 绝对不是您想要的方法,因为它将没有时间将其字典建立到足以在单个数据包结束时产生重大压缩结果的大小。在这种情况下获取真正有效的压缩的唯一机会,在我看来,是使用硬编码字典。
(关于以上所有内容的补充:正如 Michael Kohne 指出的那样,发送 JSON 意味着您可能正在发送所有文本,这意味着您正在低效地使用具有发送比您使用的更广泛字符范围的带宽。然而,将落在 0-127 范围内的字符打包到容器中的问题很简单,我认为可以留给读者作为 "练习"。)

对于上面的例子,将数据存储在SOA格式而不是AOS格式中可以大大减少数据量。我发现对于许多情况来说这是一种很好的“压缩”方法,但具体应用是否适合SOA则取决于特定的应用场景。 - Chris
2号建议有些混淆-即使每个数据包很大,LZW仍然不是正确的方法吗?如果数据包不需要单独压缩怎么办?此外,有关将0-255打包成0-127的任何详细信息或链接都将非常有帮助。 - Dmitri Zaitsev
它将0-127打包成0-255,而不是相反。 ASCII使用8位字节,但标准文本的字符仅使用较低的7位;另外128个字符将最高位设置为1,这些字符是控制字符。为了打包字符,您需要取每个第八个字符,并将其七个数据位分配给前7个字符未使用的“高位”。 - afeldspar

6

还有两种JSON压缩算法:CJson和HPack。HPack的效果非常好,与gzip压缩相当。


3
以下是关于JSON数据可压缩性的简短测试: 原始文件:crime-data_geojson.json,大小为72844字节。 (您可以在此处获取该文件:https://github.com/lsauer/Data-Hub。该文件是随机选择的,但不能代表平均JSON数据)
除了zip之外,所有存档参数都设置为“超级”。
* cm/ nanozip: 
  > 4076/72844
  [1] 0.05595519
* gzip:
  > 6611/72844
  [1] 0.09075559
* LZMA / 7zip
  > 5864/72844
  [1] 0.0805008
* Huffman / zip:
  > 7382/72844
  [1] 0.1013398
* ?/Arc:
  > 4739/72844
  [1] 0.06505683

这意味着压缩非常高效且有益。JSON数据通常具有很高的熵。根据维基百科,英文文本的熵率在每个字母1.0到1.5位之间[1],或者根据Shannon基于人类实验估计,低至每个字母0.6到1.3位。而JSON数据的熵通常远高于此。(在对10个大小大致相等的任意JSON文件进行实验时,我计算出其熵为2.36)

我不是唯一知道NanoZip的人!+1 :D (但我永远不会在线上使用它lol) - Camilo Martin

2

我发现压缩算法比选择其他格式更有效。如果这是“实时”压缩,我建议调查一下低级别的Brotli或Zstandard压缩器(高级别的需要大量CPU - 但确实提供非常好的压缩效果)。

如果您想阅读所有备选方案以及我是如何得出结论的,请查看Lucidchart技术博客的完整细节。


2

如果你正在实现在线压缩,那么你控制连接的两端,对吗?在这种情况下,如果JSON协议太大了,为什么不选择一个不那么大的不同的协议呢?我的意思是,我理解使用JSON这样的标准的吸引力,但如果你担心带宽问题,那么你可能应该选择一个不全是文本的线路协议。


4
“那么你可能应该选择一个不完全基于文本的通信协议。” 举个例子?(如果您能提供两个或更多例子,将会加1分;-)) - tobsen
@tobsen TCP, IP, UDP?但是,整个互联网使用HTTP已经很久了,从未出现过问题(SPDY正在开发中)。 - Camilo Martin
此外,关于文本与二进制的比较...将Windows注册表与Linux全文本方法进行比较,并告诉我哪个更快...文本并不意味着慢。 - Camilo Martin
@CamiloMartin 我认为这里混淆了"on the wire protocol"和"wire format"的概念。我正在寻找类似ASN1、XDR、ProtocolBuffers(还有其他的吗?)这样的"wire format"替代方案,而不是"wire protocols"。JSON并不是一种协议。 - tobsen
@tobsen 噢,是的。但是SOAP可以被称为协议,对吧?所以JSON版本也可以。我想这就是回答者所说的“协议”的意思。 - Camilo Martin
@Camilo Martin,JSON是一种格式,TCP、UDP和IP是协议。当然,HTTP运行在TCP和IP之上,这意味着您可以使用这些协议发送JSON,或者您可以选择一种更高效(从数据大小的角度来看)的二进制格式,这可能是您想要的。 - pjcard

2

让网络服务器使用 gzip 或 deflate 进行压缩,让浏览器进行本地解压缩。


这不是一个网页服务器。客户端是一个Flash程序。 - ryeguy

0

Gzip(缩小算法)在压缩方面相当不错,虽然像所有优秀的压缩算法一样,会占用很多 CPU 资源(在我的测试中,比 JSON 读/写的开销多 3-5 倍)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接