syntax="proto3";
message simple{
int32 id=1;
string name=2;
repeated string girls=3;
}
//传入类的名字
google::protobuf::Massage*create_message()const char*type_name){
google::protobuf::Massage*message=NULL;
//拿到这个类的descriptor
const google::protobuf::Descriptor* descriptor=
google::protobuf::DescriptorPool::generated_pool()->FindMesaageTypeByName(type_name);
if(descriptor){
//根据descriptor拿到想要的信息
const google::protobuf::Message* prototype=
google::protobuf::MessageFactor::generted_factory()->GetPrototype(descriptor);
if(prototype){
message=prototype->New();//new这个类
}
}
return message;
}
//利用反射获取message类里面的内容
void traverse_message(google::protobuf::Message* msg){
if(!msg){
std::cout<<"msg is NULL"<<std: :endl;
return;
}
//拿到消息类的描述des和反射ref
const google::protobuf::Descriptor* des=msg->GetDescriptor();
const google::protobuf::Reflection* ref = msg->GetReflection();
//通过描述遍历类里面的属性字段
for (int i=0; i < des->field_count(); i++){
//确定字段类型(字段描述fd)
const google::protobuf::FieldDescriptor* fd = des->field(i);
//1.可以通过字段描述拿到每个具体字段的**属性名**
printf("........filed:\t%s\n", fd->name().c_str());
//3.若字段属性为repeated,即数组类型,则再拿里面的值
if (fd->is_repeated()){
//遍历数组
for (int walk = 0; walk < ref->FieldSize(*msg,fd); walk++){
switch(fd->cpp_type(){
//判断数组类型是否INT32
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32;
{
printf("element: %d\n", ref->GetRepeatedInt32(*msg,fd, walk));
break;
}
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING;
{
printf("element: %s\n",ref->GetRepeatedString(*msg,fd,walk));
break;
}
}
}
continue;
}
//2.可以通过字段描述拿到每个具体字段的属性名**对应的属性值**
//遍历cpp类型:int32,int64,double,float,bool,enum,string,message等
switch (fd->cpp_type()) {
//获取类型INT32的属性
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32;
{
printf("value: %d\n", ref->GetInt32(*msg,fd));
break;
}
// 获取类型STRING的属性
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING;
{
printf("value: %s\n", ref->GetString(*msg,fd).c_str());
break;
}
}
}
}
int main (){
GOOGLE_PROTOBUF_VERIFY_VERSION;
auto msg=create_message("simple");//通过字符串名字创建Message类,反射设计模式
//给创建的Message类中的属性设置新值
simple* item_ptr =(simple)*msg;
const google::protobuf::Descriptor* des=msg->GetDescriptor();
const google::protobuf::Reflection* ref=msg->GetReflection();
//在描述里面找到属性名
cosnt google::protobuf::FieldDescriptor* fd_des=des->FindFieldByName("name");
//通过反射设置属性值
if(fd_des){
ref->SetString(msg,fd_des,"weixiaobao");
}
//找到序号为1的属性
fd_des=des->FindFieldByNumber(1);
//对序号为1的属性设值
ref->SetInt32(msg,fd_des,10086);
//找到第三个属性(repeated) ,可设置多个值
fd_des=des->FindFieldByName("girls");
ref->AddString(msg,fd des,"qiuxiang");
ref->AddString(msg, fd_des,"xiaofang") ;
ref->AddString(msg,fd_des,"axiang");
traverse_message(item_ptr));
std::string json=to_json(item_ptr);//将message类反序列化转为json
cout<<"json:"<<json<<endl;
}
Convierta el contenido del mensaje a json:
//利用反射获取message类里面的内容,将内容反序列化转为json
std::string to_json(google::protobuf::Message* msg){
std::string json("{")
if(!msg){
std::cout<<"msg is NULL"<<std: :endl;
return std::string("");
}
//拿到消息类的描述des和反射ref
const google::protobuf::Descriptor* des=msg->GetDescriptor();
const google::protobuf::Reflection* ref = msg->GetReflection();
//通过描述遍历类里面的属性字段
for (int i=0; i < des->field_count(); i++){
//确定字段类型(字段描述fd)
const google::protobuf::FieldDescriptor* fd = des->field(i);
//1.可以通过字段描述拿到每个具体字段的**属性名**
printf("........filed:\t%s\n", fd->name().c_str());
//3.若字段属性为repeated,即数组类型,则再拿里面的值
if (fd->is_repeated()){
json+="\"";
json+=fd->name();
json+="\":[";
//遍历数组
for (int walk = 0; walk < ref->FieldSize(*msg,fd); walk++){
switch(fd->cpp_type(){
//判断数组类型是否INT32
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32;
{
google::protobuf::int32 item = ref->GetRepeatedInt32(*msg,fd, walk);
std::string item_str=to_string(item);
json+=item_str;
if(walk!=ref->FieldSize(*msg,fd)){
//如果不是最后一个,json还得加一个,
json+=",";
}
break;
}
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING;
{
json+="\"";
json+=ref->GetRepeatedString(*msg,fd,walk).c_str();
json+="\"";
if(walk!=ref->FieldSize(*msg,fd)){
//如果不是最后一个,json还得加一个,
json+=",";
}
break;
}
}
}
json+="]";
continue;
}
//2.可以通过字段描述拿到每个具体字段的属性名**对应的属性值**
//遍历cpp类型:int32,int64,double,float,bool,enum,string,message等
switch (fd->cpp_type()) {
//获取类型INT32的属性
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32;
{
json+="\"";
json+=fd->name();
json+="\":";
google::protobuf::int32 item = ref->GetInt32(*msg,fd));
std::string item_str=to_string(item);
json+=item_str;
if(i!=des->field_count()-1){
//如果不是最后一个,json还得加一个,
json+=",";
}
break;
}
// 获取类型STRING的属性
case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING;
{
json+="\"";
json+=fd->name();
json+="\":";
json+="\"";
json+=ref->GetString(*msg,fd).c_str();
json+="\"";
if(i!=des->field_count()-1){
//如果不是最后一个,json还得加一个,
json+=",";
}
break;
}
}
}
json+="}";
return json;
}