协慌网

登录 贡献 社区

JSON 字符串中的二进制数据。比 Base64 更好的东西

JSON 格式本身不支持二进制数据。必须对二进制数据进行转义,以便可以将其放入 JSON 中的字符串元素(即,使用反斜杠转义的双引号中的零个或多个 Unicode 字符)。

逃脱二进制数据的一种明显方法是使用 Base64。但是,Base64 具有很高的处理开销。它还将 3 个字节扩展为 4 个字符,这导致数据大小增加了约 33%。

一个用例是CDMI 云存储 API 规范的 v0.8 草案。您可以使用 JSON 通过 REST-Webservice 创建数据对象,例如

PUT /MyContainer/BinaryObject HTTP/1.1
Host: cloud.example.com
Accept: application/vnd.org.snia.cdmi.dataobject+json
Content-Type: application/vnd.org.snia.cdmi.dataobject+json
X-CDMI-Specification-Version: 1.0
{
    "mimetype" : "application/octet-stream",
    "metadata" : [ ],
    "value" :   "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
    IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
    dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
    dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
    ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=",
}

是否有更好的方法和标准方法将二进制数据编码为 JSON 字符串?

答案

根据 JSON 规范,有 94 个 Unicode 字符可以表示为一个字节(如果 JSON 以 UTF-8 格式传输)。考虑到这一点,我认为您可以在空间上做到最好的是base85 ,它代表四个字节五个字符。但是,这仅比 base64 改善了 7%,计算成本更高,并且实现比 base64 少,因此这可能不是胜利。

您还可以简单地将每个输入字节映射到 U + 0000-U + 00FF 中的相应字符,然后执行 JSON 标准要求的最小编码以传递这些字符;这样做的好处是所需的解码比内置函数要少零,但是空间效率很差 - 扩展 105%(如果所有输入字节均等的可能性),而 base85 为 25%,base64 为 33%。

最终判决:BASE64 胜,在我看来,其理由是它的普通,简单,不差足以保证更换。

另请参阅: Base91Base122

我遇到了同样的问题,并认为我会共享一个解决方案: multipart / form-data。

通过发送多部分形式,您首先以字符串形式发送JSON 元数据,然后分别以原始二进制文件(图像,wav 等)发送,并由Content-Disposition名称索引。

这是一个很好的教程,说明如何在 obj-c 中执行此操作,这是一篇博客文章,介绍了如何使用形式边界对字符串数据进行分区,并将其与二进制数据分开。

您真正需要做的唯一更改是在服务器端。您将必须捕获元数据,该元数据应适当地引用 POST 的二进制数据(通过使用 Content-Disposition 边界)。

当然,这需要在服务器端进行其他工作,但是如果要发送许多图像或大图像,这是值得的。如果需要,可以将其与 gzip 压缩结合使用。

恕我直言,发送 base64 编码的数据是一种攻击; RFC multipart / form-data 是针对以下问题创建的:将二进制数据与文本或元数据结合发送。

BSON(二进制 JSON)可能适合您。 http://en.wikipedia.org/wiki/BSON

编辑:仅供参考。如果您正在寻找一些 C#服务器端的爱,.NET 库 json.net 支持读写 bson。