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

JSON字符串中的二进制数据。比Base64更好的东西,json,base64,Json,Base64,本机不支持二进制数据。必须对二进制数据进行转义,以便将其放入JSON中的字符串元素(即使用反斜杠转义的双引号中的零个或多个Unicode字符) 转义二进制数据的一个明显方法是使用Base64。但是,Base64有很高的处理开销。它还将3个字节扩展为4个字符,从而使数据大小增加了约33% 这方面的一个用例是v0.8草案。您可以使用JSON通过RESTWebService创建数据对象,例如 PUT /MyContainer/BinaryObject HTTP/1.1 Host: cloud.exam

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

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

这方面的一个用例是v0.8草案。您可以使用JSON通过RESTWebService创建数据对象,例如

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字符串?

yEnc可能适合您:

“yEnc是一种用于传输二进制数据的二进制到文本编码方案 [text]中的文件。与以前基于美国ASCII的文件相比,它减少了开销 使用8位扩展ASCII编码方法的编码方法。 yEnc的开销通常是(如果每个字节值大约显示 平均频率相同)仅为1–2%,而 uuencode和Base64等6位编码方法的开销为33%–40%。 …到2003年,yEnc成为事实上的标准编码系统 Usenet上的二进制文件。“


然而,yEnc是一种8位编码,因此将其存储在JSON字符串中与存储原始二进制数据有着相同的问题——以天真的方式进行存储意味着要进行100%的扩展,这比base64更糟糕。

因为您正在寻找将二进制数据强制转换为严格基于文本且非常有限的格式的能力,我认为Base64的开销与您期望使用JSON维护的便利性相比是最小的。如果需要考虑处理能力和吞吐量,那么您可能需要重新考虑您的文件格式。

7年后编辑:Google Gears不见了。忽略此答案。)


Google Gears团队遇到了缺少二进制数据类型的问题,并试图解决这个问题:

JavaScript有一个用于文本字符串的内置数据类型,但没有用于二进制数据的数据类型。Blob对象试图解决此限制


也许你可以用某种方式把它编织起来。

根据JSON规范,有94个Unicode字符可以表示为一个字节(如果你的JSON是以UTF-8传输的)。考虑到这一点,我认为最好的做法是在空格方面将四个字节表示为五个字符。然而,与base64相比,这只提高了7%,计算成本更高,而且实现不如base64常见,因此这可能不是一个胜利

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

最终裁决:在我看来,base64获胜的理由是它很普通、简单,而且还不至于糟糕到需要更换


另请参见:和

虽然base64确实具有约33%的扩展率,但处理开销远大于此并不一定正确:它实际上取决于您使用的JSON库/工具包。编码和解码是简单的直接操作,甚至可以优化wrt字符编码(因为JSON只支持UTF-8/16/32)——对于JSON字符串条目,base64字符始终是单字节。 例如,在Java平台上,有一些库可以相当有效地完成这项工作,因此开销主要是由扩展的大小造成的

我同意前面的两个答案:

  • base64是一个简单、常用的标准,因此不太可能找到更好的方法专门用于JSON(postscript等使用base-85;但考虑到它的好处,最多只能算是微不足道的)
  • 根据您使用的数据,编码前(和解码后)的压缩可能非常有意义

如果要处理带宽问题,请先尝试在客户端压缩数据,然后再对其进行base64压缩

这种魔力的一个很好的例子是at,关于这个主题的更多讨论在

BSON(二进制JSON)可能适合您。

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

它的编码、解码和压缩速度非常快

速度比较(基于java但有意义):

它也是JSON的扩展,允许您跳过字节数组的base64编码


当空间非常重要时,可以压缩Smile编码的字符串

数据类型非常重要。我已经测试了从RESTful资源发送有效负载的不同场景。对于编码,我使用了Base64(Apache)和压缩GZIP(java.utils.zip.*)。有效负载包含有关胶片、图像和音频文件的信息。我对图像和音频文件进行了压缩和编码,这大大降低了性能。压缩前的编码结果很好。图像和音频内容以编码和压缩字节[]的形式发送

参考:

它描述了一种使用“CDMI内容类型”操作在CDMI客户端和服务器之间传输二进制数据的方法,而无需对二进制数据进行base64转换


如果可以使用“非CDMI内容类型”操作,则将“数据”传输到对象或从对象传输数据是理想的选择。元数据随后可以作为后续的“CDMI内容类型”操作添加/检索到对象中。

UTF-8的问题在于它不是最节省空间的编码。此外,一些随机二进制字节序列是无效的UTF-8编码。因此,您不能仅仅将随机二进制字节序列解释为一些UTF-8数据,因为它将是无效的UTF-8编码。这种对UTF-8编码的限制的好处是,它使它成为ro