Кодирование и декодирование двоичных данных для включения в JSON с Python 3 - PullRequest
0 голосов
/ 27 декабря 2018

Мне нужно выбрать схему для включения двоичных элементов в объект сообщения, чтобы он мог быть снова декодирован на принимающей стороне (в моем случае потребитель в очереди Rabbit MQ / AMQP).

Я решил отказаться от многокомпонентного кодирования MIME через JSON, в основном потому, что кажется, что он использует молот Тора, чтобы протолкнуть большой палец.Я решил не связывать вручную части (двоичные и 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))

Мой гугл-фу не позволил мне подтвердить, действительно ли то, что я делаю, действительно.В частности, меня беспокоит правильность строки, которая генерирует строку из двоичных данных для включения в JSON, например, строка return base64.b64encode(byte_obj).decode('utf-8')

И, похоже, я могу вернуться к декодированию обратнов двоичные данные, так как метод base64.b64decode() обрабатывает данные UTF-8, как если бы они были ASCII - как и следовало ожидать, что они будут поступать с выходных данных base64.b64encode() ... Но действительно ли это допустимое предположение во всех случаях?

В основном я удивлен тем, что не могу найти в Интернете ни одного примера, как это сделать.Возможно, мое терпение Google все еще в отпуске!

1 Ответ

0 голосов
/ 27 декабря 2018

Документы подтверждают, что ваш подход в порядке.

base64.b64encode(byte_obj).decode('utf-8') правильно - base64.b64encode требует байтов в качестве ввода:

Кодирование байтов-подобный объект s использует Base64 и возвращает закодированные байты.

Однако base64.b64decode принимает байтов или строку ascii:

Декодирует Base64закодированный байтовоподобный объект или строка ASCII и возвращающие декодированные байты.

...