使用TinyCBOR编解码Test类时数据读取异常,请求排查原因
问题分析与解决方案
你当前的核心问题是没有将Test类的成员包装成CBOR的复合类型(如数组/映射),而是直接在顶级连续编码三个独立值,同时解码阶段也没有正确处理多值的解析逻辑,导致重复读取和类型错误。
为什么会出现这个问题?
CBOR允许顶级存在多个数据项,但TinyCBOR的解析器默认从单个顶级值开始处理。你直接依次编码三个值的话,解析器只会定位到第一个int值,后续读取操作因为没有正确推进到下一个顶级数据项,所以重复读取了第一个int;而读取float时,当前解析的仍然是int类型的数据,自然会触发类型不匹配的错误——哪怕你加了cbor_value_advance_fixed,也因为没有复合类型的包裹,无法正确遍历后续的顶级值。
正确的解决方式:用CBOR数组包装对象成员
因为Test类的成员是有序的,最适合用CBOR数组来包装(如果需要更清晰的键值对应,也可以用CBOR映射),这样整个Test对象对应一个完整的CBOR数据结构,编解码逻辑更清晰也更健壮。
修改后的编码代码
int main () { Test t; t.a = 10; t.b = 20; t.c = 3.30; // Encode values uint8_t buf[40]; CborEncoder encoder; CborEncoder arrayEncoder; // 用于编码数组的子编码器 cbor_encoder_init(&encoder, buf, sizeof(buf), 0); // 创建一个包含3个元素的CBOR数组 cbor_encoder_create_array(&encoder, &arrayEncoder, 3); // 向数组中依次添加类成员 cbor_encode_int(&arrayEncoder, t.a); cbor_encode_int(&arrayEncoder, t.b); cbor_encode_float(&arrayEncoder, t.c); // 结束数组编码,完成容器闭合 cbor_encoder_close_container(&encoder, &arrayEncoder); // 解码部分见下方... }
修改后的解码代码
// 接上面的编码代码,继续解码逻辑 CborParser parser; CborValue value; CborValue arrayValue; // 用于遍历数组元素的Value对象 int a; int b; float c; cbor_parser_init(buf, sizeof(buf), 0, &parser, &value); // 先检查顶级值是否为数组,再进入容器 if (cbor_value_is_array(&value)) { cbor_value_enter_container(&value, &arrayValue); // 读取第一个int成员 cbor_value_get_int(&arrayValue, &a); cout << "Int A: " << a << endl; // 推进到数组的下一个元素 cbor_value_advance(&arrayValue); // 读取第二个int成员 cbor_value_get_int(&arrayValue, &b); cout << "Int B: " << b << endl; // 推进到数组的下一个元素 cbor_value_advance(&arrayValue); // 读取float成员,先做类型检查避免错误 if (cbor_value_is_float(&arrayValue)) { cbor_value_get_float(&arrayValue, &c); cout << "Float C: " << c << endl; } // 退出数组容器 cbor_value_leave_container(&value, &arrayValue); } return 0; }
额外说明
- 类型检查的重要性:添加
cbor_value_is_array、cbor_value_is_float这类检查,可以在数据格式不符合预期时提前处理,避免程序崩溃。 - 推进元素的正确方式:在数组中遍历元素时,使用
cbor_value_advance比cbor_value_advance_fixed更通用——后者仅适用于固定长度的简单类型,而前者可以处理所有CBOR类型的元素推进。 - 映射的替代方案:如果希望编码后的数据可读性更强(比如用键名对应类成员),可以把数组换成CBOR映射,编码时用
cbor_encoder_create_map,然后依次添加键值对(键用字符串,值对应成员),解码时通过键名查找对应的值。
内容的提问来源于stack exchange,提问作者User7723337
相关产品推荐
相关产品推荐

