25

考虑这个 JSON 响应:

[{
    Name: 'Saeed',
    Age: 31
}, {
    Name: 'Maysam',
    Age: 32
}, {
    Name: 'Mehdi',
    Age: 27
}]

这适用于少量数据,但是当您想要提供大量数据(例如数千条记录)时,以某种方式防止响应 JSON 中的属性名称重复似乎是合乎逻辑的。

我用谷歌搜索了这个概念(DRYing JSON),令我惊讶的是,我没有找到任何相关的结果。当然,一种方法是使用简单的自制算法压缩 JSON,并在使用前在客户端解压缩:

[['Name', 'Age'], 
['Saeed', 31], 
['Maysam', 32], 
['Mehdi', 27]]

但是,最佳实践会比每个尝试重新发明轮子的开发人员更好。你们有没有看到一个众所周知的被广泛接受的解决方案?

4

5 回答 5

15

首先,JSON 并不是最紧凑的数据表示方式。它意味着可以直接解析为一个 javascript 数据结构,该数据结构旨在立即使用,无需进一步解析。如果你想优化大小,那么你可能不希望自我描述 JSON,你需要让你的代码对如何处理数据和使用它做一些假设,并对接收进行一些手动解析结尾。正是这些假设和额外的编码工作可以为您节省空间。

如果代码已经知道服务器响应的属性名称和格式,则可以将数据作为交替值数组返回:

['Saeed', 31, 'Maysam', 32, 'Mehdi', 27]

或者如果可以安全地假设名称不包含逗号,您甚至可以只返回一个逗号分隔的字符串,您可以将其拆分为各个部分并粘贴到您自己的数据结构中:

"Saeed, 31, Maysam, 32, Mehdi, 27"

或者,如果您仍然希望它是有效的 JSON,您可以将该字符串放在这样的数组中,这仅比我的第一个版本稍好,其中项目本身是数组元素:

["Saeed, 31, Maysam, 32, Mehdi, 27"]

这些假设和紧凑性将更多的责任放在了在您自己的 javascript 上解析数据的责任中,但正是移除了您开始使用的完整 JSON 的自我描述性质,这导致其更紧凑的性质。

于 2012-12-30T07:53:11.310 回答
10

一种解决方案称为 hpack 算法

https://github.com/WebReflection/json.hpack/wiki

于 2012-12-30T07:31:09.460 回答
7

您可能可以使用 CSV 格式而不是 JSON,因为您只需指定一次属性名称。但是,这将需要像您的示例中那样的刚性结构。

JSON 并不是真正适合 DRY 的东西,因为考虑到你可以用它做什么,它已经被很好地打包了。就个人而言,我将裸数组用于存储在文件中供以后使用的 JSON 数据,但对于简单的 AJAX 请求,我只是保持原样。

DRY 通常是指您自己编写的内容,因此如果您的对象是动态生成的,您无论如何都不应该担心它。

于 2012-12-30T07:33:39.090 回答
5

使用通常很容易内置到大多数 Web 服务器和客户端中的 gzip 压缩?

在每一端生成和解析 JSON 仍然需要一些(额外的)时间和内存,但通过网络发送不会花费太多时间,并且代表您需要最少的实施工作。

即使您以某种方式预压缩源数据,也可能值得一试。

于 2012-12-30T11:24:26.090 回答
1

对于 JSON 来说,经常有大量字符串或“属性”重复实际上不是问题(XML 也不是)。

这正是 DEFLATE 算法地址的重复字符串消除组件(由 GZip 使用)。

虽然大多数浏览器客户端可以接受 GZip 压缩响应,但返回服务器的流量不会。

这是否保证使用“JSON 压缩”(即hpack或其他方案)?

  1. 它不太可能比在 Javascript 中实现 GZip 压缩快得多(这并非不可能;在相当快的机器上,您可以在 250 毫秒内压缩 100 KB)。

  2. 安全地处理不受信任的 JSON 输入非常困难。您需要使用基于流的解析并确定最大复杂度阈值,否则您的服务器可能会大吃一惊。例如,参见 Armin Ronacher 的Start Writing More Classes

    如果您整洁的小型 Web 服务器每秒通过 gevent 收到 10000 个请求,但使用的是 json.loads,那么我可能会通过向其发送 16MB 精心设计和嵌套的 JSON 来使其爬行停止,这些 JSON 会占用您所有的 CPU。

于 2013-03-01T09:41:20.257 回答