当前位置:网站首页>protobuf 中复合数据类型的读写
protobuf 中复合数据类型的读写
2022-07-30 04:33:00 【litanyuan】
背景
protobuf 在生成的 C++ 代码中为 .proto 文件中的每个 message 生成了对应的 C++ 类,并提供了数据成员的读写方法。
message 类型读写
①.message 示例
message Point
{
double lng = 1;
double lat = 2;
}
message DemoMsg
{
int32 id = 1;
Point pos = 2;
}
②.成员赋值
通过 mutable_xxx 方法返回的指针给成员赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
msg.mutable_pos()->set_lng(112.56);
msg.mutable_pos()->set_lat(56.78);
cout << msg.DebugString() << endl;

通过 copyFrom 方法使用结构体赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
msg.mutable_pos()->CopyFrom(m_p);
cout << msg.DebugString() << endl;
通过 set_allocated_xxx 成员函数传入指针进行赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
protoTest::Point * m_p = new protoTest::Point;
m_p->set_lng(112.56);
m_p->set_lat(56.78);
msg.set_allocated_pos(m_p);
cout << msg.DebugString() << endl;
③.成员读取
通过成员函数 has_xxx 可以判断 message 类型的成员是否被赋值。
protoTest::Point* m_p = new protoTest::Point;
m_p->set_lng(112.56);
m_p->set_lat(56.78);
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_allocated_pos(m_p);
if (msg.has_pos())
{
auto& pos = msg.pos();
cout << pos.lng() << " " << pos.lat();
}

map 类型读写
①.message 示例
message DemoMsg
{
map<int32,string> a = 1;
}
②.成员赋值
map 类型成员赋值需通过 mutable_xxx 方法进行:
protoTest::DemoMsg msg;
msg.mutable_a()->insert({
1,"aaaaa" });
msg.mutable_a()->insert({
2,"bbbbb" });
msg.mutable_a()->insert({
3,"ccccc" });
cout << msg.DebugString() << endl;

③.成员读取
protoTest::DemoMsg msg;
msg.mutable_a()->insert({
1,"aaaaa" });
msg.mutable_a()->insert({
2,"bbbbb" });
auto map = msg.mutable_a();
if (map->contains(1))
{
cout << map->at(1) << endl;
}

any 类型读写
①.概述
any 可以保存任意的已知类型的序列化数据,常用于对结构体数据的再包装,即可以把不同类型的 message 包装在同一个 message 中进行传输。
②.message 示例
syntax = "proto3";
import "google/protobuf/any.proto";
package protoTest;
message Point
{
double lng = 1;
double lat = 2;
}
message Node
{
int32 id = 1;
string name = 2;
}
message DemoMsg
{
int32 id = 1;
google.protobuf.Any data = 2;
}
③.成员赋值
使用 any 类型的成员函数 PackFrom 来进行赋值。
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
protoTest::DemoMsg msg;
msg.set_id(1);
msg.mutable_data()->PackFrom(m_p);
cout << msg.DebugString() << endl;

④.message 类型判断
通过成员函数 Is 可以判断是否为指定类型的数据。
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
protoTest::Node m_node;
m_node.set_id(1);
m_node.set_name("Zhangsan");
protoTest::DemoMsg msg1;
msg1.set_id(1);
msg1.mutable_data()->PackFrom(m_p);
protoTest::DemoMsg msg2;
msg2.set_id(2);
msg2.mutable_data()->PackFrom(m_node);
auto checkAny = [&](const protoTest::DemoMsg& msg) {
if (msg.data().Is<protoTest::Point>())
cout << " msgID:" << msg.id() << " 中 data 类型为 Point " << endl;
else if( msg.data().Is<protoTest::Node>() )
cout << " msgID:" << msg.id() << " 中 data 类型为 Node " << endl;
};
checkAny(msg1);
checkAny(msg2);

⑤.成员读取
通过成员函数 UnpackTo 可以把 any 数据还原成对应的结构体数据。
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
protoTest::DemoMsg msg;
msg.set_id(1);
msg.mutable_data()->PackFrom(m_p);
if (msg.data().Is<protoTest::Point>())
{
protoTest::Point pos;
if (msg.data().UnpackTo(&pos))
{
cout << pos.DebugString() << endl;
}
}

oneof 类型读写
①.概述
oneof 类型同 C++ 中的 union 类型,同一时刻只有一种类型有效。
②.message 示例
message DemoMsg
{
oneof test{
int32 id = 1;
string name =2;
};
}
③.成员赋值
直接使用 set_xxx 给相应的成员赋值即可,但只有最后一次赋值的数据有效。
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
cout << msg.DebugString() << endl;
④.数据类型判断
通过 has_xxx 方法判断对应类型成员是否赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
if (msg.has_name())
{
cout << "msg 中为 string 类型" << endl;
}

通过 xxx_case 方法当前判断保存的成员类型:
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
switch (msg.test_case())
{
case protoTest::DemoMsg::kId:
cout << "msg 中为 int32 类型" << endl; break;
case protoTest::DemoMsg::kName:
cout << "msg 中为 string 类型" << endl; break;
default:
break;
}
⑤.成员读取
先判断当前保存的字段类型,再读取数据。
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
switch (msg.test_case())
{
case protoTest::DemoMsg::kId:
cout << msg.id() << endl; break;
case protoTest::DemoMsg::kName:
cout << msg.name() << endl; break;
default:
break;
}


边栏推荐
- SSM框架简单介绍
- The first immersive and high-fidelity metaverse in China, Xiyuan Universe is officially launched
- [C language] Program environment and preprocessing
- A brief introduction to the SSM framework
- Install MySQL Database on Kylin V10 Operating System
- @WebServlet注解(Servlet注解)
- Shanxi group (enterprises) in the second network security skills competition part problem WP (8)
- LeetCode 114. Expand Binary Tree into Linked List (One Question Three Eats)
- file system two
- PyG搭建R-GCN实现节点分类
猜你喜欢

Usage of exists in sql
![[Linear table] - Detailed explanation of three practice questions of LeetCode](/img/71/91ba0cc16fe062c1ac9e77e1cc8aa2.png)
[Linear table] - Detailed explanation of three practice questions of LeetCode

2.6基数排序(桶排序)

精品MySQL面试题,备战八月99%必问!过不了面试算我的

2.4希尔排序

DAY17、CSRF 漏洞

恐造成下一个“千年虫”的闰秒,遭科技巨头们联合抵制

验证addShutdownHook钩子生效

sql statement - how to query data in another table based on the data in one table
![Advanced [C] array to participate in the function pointer](/img/00/67dd77463670c8ebd5d004dbe12549.jpg)
Advanced [C] array to participate in the function pointer
随机推荐
验证addShutdownHook钩子生效
我的Go+语言初体验——祝福留言小系统,让她也可以感受到你的祝福
Simple experiment with BGP
MySQL 安装报错的解决方法
QT(39)-vs开发qt程序提示无法打开源文件
商品管理系统数据库设计--SQL Server
sqlmap use tutorial Daquan command Daquan (graphics)
DAY17, CSRF vulnerability
2.4希尔排序
Usage of exists in sql
SQLSERVER merges subquery data into one field
The implementation and basic operation of sub-database sub-table, ER table, global table, fragmentation rules, global sequence, etc. in MyCat
Thinkphp 5.0.24 Variable Override Vulnerability Causes RCE Analysis
数据目录是什么?为何需要它?
file system two
DAY17、CSRF 漏洞
The VUX Datetime component compute-days-function dynamically sets the date list
Go study notes (84) - Go project directory structure
05全局配置文件application.properties详解
MNIST of Dataset: MNIST (handwritten digital image recognition + ubyte.gz file) data set introduction, download, usage (including data enhancement) detailed guide