msgpack:在不知道类型的情况下解压缩自定义类

时间:2019-11-14 14:38:31

标签: c++ msgpack

这是我打包和解压缩已知类的代码段:

MessageCoffeeIsReady input(1, "Black coffee is ready");

// ---- Serialize to buffer
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, input);

// ---- Send over line...

// ---- Unpack received buffer
msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size());
msgpack::object        obj = oh.get();

// ---- Convert to message
MessageCoffeIsReady result; // <- How do i know the msgpack::object contains `MessageCoffeIsReady`?
obj.convert(result);

我的课看起来像这样:

class MessageCoffeeIsReady : public MessageBase
{
    protected:

        std::string m_name;
        int         m_id;

    public:

        MessageCoffeeIsReady(int id, std::string name)
        { m_id = id; m_name = name; }

        MSGPACK_DEFINE (m_name, m_id);
};

我的问题是:我怎么知道我收到了MessageCoffeIsReady类型的消息?

我可以使用任何内部typeid转换为特定类吗?

1 个答案:

答案 0 :(得分:1)

MsgPack是一种类似于JSON的格式,在其协议中不支持用户定义的类型。使用MSGPACK_DEFINE宏时,它只会映射

但是,您仍然可以添加自己的类型标签来支持诸如已区分的联合之类的东西。那不会让您识别任何任意对象,但是如果您只打算发送几种类型的对象之一,则非常适合。

struct Any {
    std::string type;
    msgpack::object data;
    MSGPACK_DEFINE(type, data);
};

这存储了一个对象和一个用于标识该对象的字符串(类型)。然后,您可以将对象打包到其中:

struct Foo {
    int a;
    std::string b;
    MSGPACK_DEFINE(a, b);
};

struct Bar {
    double c;
    MSGPACK_DEFINE(c);
};

/* ... */

auto foo = Any { "foo", msgpack::object(Foo { 42, "hi" }, z) };
auto foo_obj = msgpack::object(foo, z);
auto bar = Any { "bar", msgpack::object(Bar { 25.5 }, z) };
auto bar_obj = msgpack::object(bar, z);

要弄清楚事情,请先将其转换为任意。然后根据标签将其转换为不同的类型:

Any any;
obj.convert(any);
if (any.type == "foo") {
    Foo foo;
    any.data.convert(foo);
    std::cout << "foo(a=" << foo.a << ", b=" << foo.b << ")\n";
} else if (any.type == "bar") {
    Bar bar;
    any.data.convert(bar);
    std::cout << "bar(c=" << bar.c << ")\n";
}

当然,只有在您对所看到的对象有一定控制权的情况下。如果您真的想获取详细信息,则可以手动检查基础的类似于JSON的数据。这是来自文档的示例:

if (o.type != msgpack::type::ARRAY) throw msgpack::type_error();
if (o.via.array.size != 2) throw msgpack::type_error();
v = my_class(
    o.via.array.ptr[0].as<std::string>(),
    o.via.array.ptr[1].as<int>());

然后由您来验证所检查的对象是否有效。

相关问题