пользовательские объекты msgpack python

Я общаюсь с другой системой, которая использует msgpack. Пытались упаковать и распаковать пользовательские объекты с помощью пакета msgpack python. Но сделать это как следует не удалось.

Сообщения, которые представляют собой массивы, имеют следующую структуру:

[Header, Payload]

здесь определено в классе, который я называю Message.

Заголовок представляет собой массив длиной два целых числа [number, type]. Payload однако это карта с целочисленными ключами. Внутри Payload также есть карты с целыми ключами. Итак, у меня может быть полезная нагрузка, которая выглядит так:

{ 
  7: {8: 0.1}, 
  1: {1: 1.3}
}

Я написал метод для кодирования такого сообщения

def encode(obj):
    if isinstance(obj, Message):
        return [obj.header, obj.payload]
    elif isinstance(obj, Header):
        return [obj.number, obj.type]
    elif isinstance(obj, Payload):
        return obj.data

    raise ValueError(f"Wrong input for message. This object is given {obj}")

где Payload определяется как класс со словарем:

class Payload:
    def __init__(self) -> None:
        self.data = {}

Я могу закодировать сообщение с помощью

message = Message()
packed = msgpack.packb(message, default=encode)

Но я не могу расшифровать его с помощью msgpack.unpackb. Основываясь на короткой документации, я расшифровываю так

unpacked = msgpack.unpackb(packed, object_hook=decode, strict_map_key=False)

Чего я не знаю, так это того, как правильно написать метод декодирования. Если я определяю функцию decode следующим образом:

def decode(packed_obj):
    print(f'decode called with {packed_obj}')

Я получаю этот вывод

decode called with {8: 0.1}
decode called with {1: 1.3}
decode called with {1: None, 7: None}

Кажется, что msgpack начинает с вызова метода для самых глубоких словарей, а затем продвигается вверх. Но я изо всех сил пытаюсь восстановить объект Payload.

Я думал, что смогу просмотреть действительные ключи, и если значение является числом с плавающей запятой, то я знаю, что это внутренний словарь. Но функция декодирования должна в итоге вернуть объект класса Message.

Я использую python 3.6 и msgpack 1.0.0, который устанавливается вместе с pip.


person Keivan    schedule 01.11.2020    source источник


Ответы (1)


Оставив ответ здесь на случай, если кто-нибудь доберется до этого позже. Решение состоит в том, чтобы отделить распаковку от декодирования. Примитивные типы автоматически распаковываются без необходимости использования специальной функции декодирования.

Итак, в примере этот словарь можно напрямую кодировать и декодировать:

{ 
  7: {8: 0.1}, 
  1: {1: 1.3}
}

Что вам нужно, так это просто вызвать unpackb без функции перехвата объекта.

unpacked = msgpack.unpackb(packed, strict_map_key=False)

Затем вы можете написать функцию для декодирования, которая получает этот словарь и декодирует его.

person Keivan    schedule 29.11.2020