C++中反序列化MsgPack匿名结构体列表(禁用Qt)
反序列化MsgPack匿名结构体列表(无Qt依赖)
方案一:使用轻量MsgPack第三方库(推荐)
选择纯C实现的MsgPack解析库(比如msgpack-c的C版本),无需Qt依赖,能轻松处理动态长度的列表和异构字段。
示例代码
#include <msgpack.hpp> #include <vector> #include <string> #include <iostream> // 定义结构体对应MsgPack的键值对(无需提前绑定,动态解析) struct AnonymousStruct { std::string field1; int field2; }; int main() { // 假设receivedBytes是接收到的MsgPack字节数据(std::vector<char>或char*) std::vector<char> receivedBytes = ...; // 解析字节流 msgpack::unpacked result; msgpack::unpack(result, receivedBytes.data(), receivedBytes.size()); msgpack::object obj = result.get(); // 验证是数组类型 if (!obj.is_array()) { std::cerr << "数据不是数组类型" << std::endl; return 1; } std::vector<AnonymousStruct> structList; // 遍历数组元素(动态处理长度) for (size_t i = 0; i < obj.via.array.size; ++i) { msgpack::object elem = obj.via.array.ptr[i]; // 验证元素是map类型(对应匿名结构体) if (!elem.is_map()) { std::cerr << "数组元素不是map类型" << std::endl; continue; } AnonymousStruct s; // 遍历map的键值对,提取字段 for (size_t j = 0; j < elem.via.map.size; ++j) { msgpack::object_key key = elem.via.map.ptr[j].key; msgpack::object val = elem.via.map.ptr[j].val; if (key.as<std::string>() == "field1") { s.field1 = val.as<std::string>(); } else if (key.as<std::string>() == "field2") { s.field2 = val.as<int>(); } } structList.push_back(s); } // 输出解析结果 for (const auto& s : structList) { std::cout << "field1: " << s.field1 << ", field2: " << s.field2 << std::endl; } return 0; }
方案二:手动解析MsgPack字节流(无第三方库)
如果不能引入任何第三方库,需要手动解析MsgPack的类型标记:
- MsgPack数组的类型标记:
- 固定长度数组:
0x90 + N(N为数组长度,1<=N<=15) - 16位长度数组:
0xdc后接2字节无符号整数表示长度 - 32位长度数组:
0xdd后接4字节无符号整数表示长度
- 固定长度数组:
- MsgPack map的类型标记(对应每个结构体):
- 固定长度map:
0x80 + N(N为键值对数量,1<=N<=15) - 16位长度map:
0xde后接2字节无符号整数表示长度 - 32位长度map:
0xdf后接4字节无符号整数表示长度
- 固定长度map:
- 字符串类型标记:
0xa0 + len(短字符串)或0xd9/0xda/0xdb(长字符串) - 整数类型标记:正整数用
0x00-0x7f(直接值)或0xcc/0xcd/0xce/0xcf(不同长度)
核心步骤
- 读取字节流的第一个字节,判断是否为数组标记,解析出数组长度
- 循环读取每个数组元素:
- 读取元素的第一个字节,判断是否为map标记,解析出键值对数量
- 循环读取每个键值对:
- 解析键(字符串类型),判断是
field1还是field2 - 根据键的类型,解析对应的值(字符串或整数)
- 解析键(字符串类型),判断是
- 将解析出的字段存入结构体,加入结果列表
手动解析需要处理字节序(MsgPack使用大端字节序)和各种边界情况,适合对依赖严格限制的场景。
内容的提问来源于stack exchange,提问作者syat-cd
相关产品推荐
相关产品推荐

