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

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

其中一个用例是CDMI云存储API规范的0.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字符串?


当前回答

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

其他回答

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

我现在的解决方案,XHR2使用ArrayBuffer。ArrayBuffer作为二进制序列,包含多种内容类型的多部分内容、视频、音频、图形、文本等。All in One Response。

在现代浏览器,有DataView, StringView和Blob为不同的组件。 详情请参见:http://rolfrost.de/video.html。

yEnc可能适合你:

http://en.wikipedia.org/wiki/Yenc

"yEnc is a binary-to-text encoding scheme for transferring binary files in [text]. It reduces the overhead over previous US-ASCII-based encoding methods by using an 8-bit Extended ASCII encoding method. yEnc's overhead is often (if each byte value appears approximately with the same frequency on average) as little as 1–2%, compared to 33%–40% overhead for 6-bit encoding methods like uuencode and Base64. ... By 2003 yEnc became the de facto standard encoding system for binary files on Usenet."

然而,yEnc是一种8位编码,因此将其存储在JSON字符串中与存储原始二进制数据有相同的问题-使用naïve方式意味着大约100%的展开,这比base64更糟糕。

如果要处理带宽问题,请先尝试在客户端压缩数据,然后再使用base64-it。

关于这种魔力的一个很好的例子是在http://jszip.stuartk.co.uk/,关于这个主题的更多讨论是在Gzip的JavaScript实现中

在Node.js中,你可以在不做任何改变的情况下将Buffer转换成字符串:

const serialized = buffer.toString("binary")
const deserialized = Buffer.from(serialized, "binary")

如果你想通过牺牲大小来获得更高的可靠性,请将"binary"替换为"base64"