编码和解码二进制数据以包含到 JSON 和 Python 3

Encoding and decoding binary data for inclusion into JSON with Python 3

我需要决定将二进制元素包含到消息对象中的模式,以便它可以在接收端再次解码(在我的情况下,Rabbit MQ/AMQP 队列上的消费者)。

我决定反对 JSON 的多部分 MIME 编码,主要是因为它看起来像是在使用 Thor 的锤子来推动图钉。我决定不手动连接部件(二进制和 JSON 连接在一起)主要是因为每次出现新需求时,它都是一个整体重新设计。 JSON 在其中一个字段中使用二进制编码似乎是一种优雅的解决方案。

我看似有效(通过比较发送和接收数据的 MD5 和确认)的解决方案正在执行以下操作:

def json_serialiser(byte_obj):
    if isinstance(byte_obj, (bytes, bytearray)):
        # File Bytes to Base64 Bytes then to String
        return base64.b64encode(byte_obj).decode('utf-8')
    raise ValueError('No encoding handler for data type ' + type(byte_obj))


def make_msg(filename, filedata):
    d = {"filename": filename,
         "datalen": len(filedata),
         "data": filedata}
    return json.dumps(d, default=json_serialiser)

在接收端我只是这样做:

def parse_json(msg):
    d = json.loads(msg)
    data = d.pop('data')
    return base64.b64decode(data), d


def file_callback(ch, method, properties, body):
    filedata, fileinfo = parse_json(body)
    print('File Name:', fileinfo.get("filename"))
    print('Received File Size', len(filedata))

我的 google-fu 让我无法确认我所做的是否真的有效。特别是我担心从二进制数据生成字符串以包含到 JSON 中的行是否正确,例如行 return base64.b64encode(byte_obj).decode('utf-8')

而且我似乎可以使用解码回二进制数据的捷径,因为 base64.b64decode() 方法处理 UTF-8 数据就好像它是 ASCII - 正如人们所期望的那样来自 base64.b64encode() 的输出...但这在所有情况下都是有效的假设吗?

最让我感到惊讶的是无法在网上找到任何这样做的例子。可能我的google耐心还在放假吧!

文档确认您的方法是正确的。

base64.b64encode(byte_obj).decode('utf-8') 是正确的 - base64.b64encode requires 字节作为输入:

Encode the bytes-like object s using Base64 and return the encoded bytes.

然而 base64.b64decode accepts 字节或 ascii 字符串:

Decode the Base64 encoded bytes-like object or ASCII string s and return the decoded bytes.