protobuf usa la reflexión para establecer el valor de la clase de mensaje y obtener el contenido del campo en la clase, y convertir la clase de mensaje al formato json

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;
}

inserte la descripción de la imagen aquí
Convierta el contenido del mensaje a json:
inserte la descripción de la imagen aquí

//利用反射获取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;
}

Supongo que te gusta

Origin blog.csdn.net/qq_37967853/article/details/130283323
Recomendado
Clasificación