C++使用protobuf嵌套结构体总结

2,272 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

前面的章节讲述了如何将protobuf环境配置到VS+Qt的环境,那么这一章节就来讲述下,如何使用并解析复杂的嵌套式protobuf结构。

今天我们就以组装以及解析两大部分分别说明吧!

今天使用的例子如下:

syntax = "proto3";

package JCProto;

message Test_st1
{
	string s1 = 1;
	string s2 = 2;
	repeated Child_Test1 test1 = 3;
}

message Child_Test1
{
	string s1 = 1;
	int32 n1 = 2;
}

当前代码只是例子,名字都是随意定义的,大家在实际项目中千万不要写成这个样子呀!你就准备接收项目经理的批评吧,哈哈!

上述protobuf说明:

首先第一句话:syntax = "proto3"; 代表是使用了protobuf3结构,这个是一定要需要写清楚的,如果不写的话,你的电脑里存在protobuf2和3两个版本的时候,最容易混淆了,大家应该懂得版本冲突的问题吧!

该protobuf中存在了两个结构:Test_st1、Child_Test1。很明显,Child_Test1是属于Test_st1的子结构,并且是一种类似于vector容器的结构体。

如果不是很清楚的,可以理解成C++版的结构体

类似C++结构.png

vector类似于repeated。也相当于数组

一开始很多人不是很理解这个关键词的意思,这么一转换就很清楚看出是什么意思了。

那么,我们来实际的功能操作吧!

功能1:组装protobuf结构体

难点:如何存储数组类的结构体?

普通的string以及int赋值很好处理,直接使用goole内部的函数就可以了,重点就讲解下如何给结构体如何赋值。

1:声明protobuf定义的结构体,Test_st1

JCProto::Test_st1 cmdTest;

JCProto这是什么呢? 类似于咱们在C++中命名空间作用,这样说大家就会很好理解了。

简单的字符串或者是整型赋值写法,如下:

std::string sContent = "需要赋值的数据";
cmdTest.set_s1(sContent);

结构体赋值写法,如下:

定义Child_Test1 结构,并设置每一条数据的赋值,类似于vector的赋值,最主要的区别在于protobuf这里不是pust_back而已。

JCProto::Child_Test1 cmdChild;
cmdChild.set_s1(); //参数是需要赋值的实际内容
cmdChild.set_n1(); //参数是需要赋值的实际内容

每一条的结构写好了,接下来,该如何赋值到repeated中呢?这也是重点哟~

第一步:需要new一个Child_Test结构数据,相当于C++中类的new的方式

JCProto::Child_Test1 *cmdChild = new JCProto::Child_Test1;
cmdChild->set_s1(); //参数是需要赋值的实际内容
cmdChild->set_n1(); //参数是需要赋值的实际内容
cmdTest->set_allocated_test1(cmdChild);

重点就是最后一句话,使用了set_allocated的方法,直接存储到cmdSt中,这里要看清楚了,不是cmdChild,而是cmdSt中!!

最后的最后,一定要记得释放你创建的资源

cmdTest.release_test1();

有些友友们,直接只用了之后早就忘记了释放资源了,这是不对的,如果你觉得手动释放麻烦,可以使用另一种方式,让goole帮你释放,例如:mutable_pos方法

但是,我不建议使用mutable_pos方法,啥也没有手动释放的安全(这是不是一个C++程序员的通病呢?)

到这里,protobuf数据就已经组装完成了,最后直接转换成json格式的字符串就可以啦!

std::string sJsonData = "";
JCJson2Pb::PbMsg2JsonStr(cmdTest, sJsonData);

主要是 PbMsg2JsonStr 方法,查阅资料大家都可以找到protobuf与json的转换函数,这里也就不再说明啦!

功能2:解析protobuf数据

功能1将protobuf转换成了json数据,那么这里,就是将json数据转换成protobuf结构了。

JCProto::Test_st1 cmdTest;
//将json数据转成protobuf结构
if (JCJson2Pb::JsonStr2PbMsg(sReceivedData, cmdTest) == false)
{
    //数据解析错误,直接返回
    return false;
}

JsonStr2PbMsg 这里重点的的转换函数,也是在protobuf与json转换中的。

此时,cmdTest中已经存储好了转换后的json结构了,那么最主要的解析还是嵌套的结构体中,repeated

因为是类似于vector的容器方式,那么,在拿数据的时候也需要使用遍历的方式。获取repeated的大小

for(int i = 0; i < cmdTest.test1_size(); i++)
{
    //在这里,处理每一条数据
    JCProto::Child_Test1 cmdChild = cmdTest.test1(i);
    //解析数据
    std::string s1 = cmdChild.s1();
    int n1 = cmdChild.n1();
}

是不是很类似于vector拿数据呢?

到这里,解析、组装 嵌套的protobuf结构已经讲解完成了,如果有不明白的可以留言哟!

我是中国好公民st,一名C++开发程序猿~