You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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字节无符号整数表示长度
  • 字符串类型标记:0xa0 + len(短字符串)或0xd9/0xda/0xdb(长字符串)
  • 整数类型标记:正整数用0x00-0x7f(直接值)或0xcc/0xcd/0xce/0xcf(不同长度)

核心步骤

  1. 读取字节流的第一个字节,判断是否为数组标记,解析出数组长度
  2. 循环读取每个数组元素:
    • 读取元素的第一个字节,判断是否为map标记,解析出键值对数量
    • 循环读取每个键值对:
      • 解析键(字符串类型),判断是field1还是field2
      • 根据键的类型,解析对应的值(字符串或整数)
  3. 将解析出的字段存入结构体,加入结果列表

手动解析需要处理字节序(MsgPack使用大端字节序)和各种边界情况,适合对依赖严格限制的场景。

内容的提问来源于stack exchange,提问作者syat-cd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:55:04