方法介绍

    protobuf的介绍在这里就不详细介绍了,主要是俺也是刚接触,感兴趣的同学可以去搜索相关博客或者直接去看源码以及google的官方文档(官方文档表示很吃力)或者去这个网站:https://developers.google.com/protocol-buffers/docs/overview查看相应内容,这里面内容很全面,可以很方面的查询各个函数的使用方法以及功能。本篇文章主要介绍一下本人最近做的一个protobuf转json的小工具,下面进行拆分讲解,完整的代码在:git@github.com:chengfeiGitHub/P-bToJson.git。

    protobuf自带一个MessageToJson()的函数可以将对应的消息转换成json,一般情况下该函数可以满足转换需求。但是,最近项目的要求使用MessageToJson()无法实现,主要要求是:

  1. 选择特定的messge进行转换(主要是提供包含需求字段号的set或者vector,根据提供的字段号进行转换);

  2. 对于Enum类型的消息,可以选择显示枚举名或者枚举值;

  3. 对于字段值为0的字段,可以选择显示或者不显示.

    主要有这三个要求,对于功能2、3现在最新的protobuf应该是支持的,但是没有功能1的实现方式,所以只好自己写一个小工具。

    说明:本工具由C++编写完成

    首先是函数的声明:

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

 1 #pragma once 2 #include <iostream> 3 #include <google/protobuf/message.h> 4 #include <google/protobuf/descriptor.h> 5  6 void ChooseSomeFieldsToJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, std::vector<uint>& needs, bool Enum_2_Str, bool Showzero); 7 //Enum_2_Str: ture显示枚举名,false:显示枚举值; Showzero: ture显示值为0的fields,false,不显示值为0的fields。 8 void GetRepeatedJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, const google::protobuf::FieldDescriptor *field, const ::google::protobuf::Reflection *reflection, bool Enum_2_Str,bool Showzero); 9 void NeedEmptyToJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, bool Enum_2_Str, bool Showzero);10 void NeedNotEmptyToJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, std::vector<uint>& needs, bool Enum_2_Str, bool Showzero);11 int AppendTmpString1(std::string& pb2jsonstring,std::string& tmp_string, int judge);12 int AppendTmpString2(std::string& pb2jsonstring,std::string& tmp_string, int judge);

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

 

    pb2jsonstring是存储转换结果的字符串,msg是需要转换的消息,needs是需要转换的字段号;函数GetRepeatedJson()是对重复的字段进行操作;NeedEmptyToJson()是当needs为空时对应的操作(needs为空表示需要转换所有的字段);NeedNotEmptyToJson()是当needs不为空时对应的操作;AppendTmpStrign1()以及AppendTmpStrign2()是将临时字符串添加到pb2jsonstring后的操作。

    上面的代码保存到一个头文件当中,就叫pbjsontest3.h吧,然后是pbjsontest3.cpp

    

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

 1 #include <iostream> 2 #include <google/protobuf/descriptor.h>  
 3 #include <google/protobuf/message.h>  
 4 #include <set> 5 #include <string> 6 #include "pbjsontest3.h" 7    8 using namespace ::google::protobuf; 
 9 10 void ChooseSomeFieldsToJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, std::vector<uint>& need, bool Enum_2_Str, bool Showzero)  
11 {12 13     const Descriptor* descriptor = msg.GetDescriptor();  
14     const Reflection* reflection = msg.GetReflection(); 
15     if (need.empty())  //如果needs为空,表示需要将所有的字段转换为json16     {    
17         NeedEmptyToJson(pb2jsonstring, msg, Enum_2_Str, Showzero);18     }19     else 20     {21         NeedNotEmptyToJson(pb2jsonstring, msg, need, Enum_2_Str, Showzero);22     }23 }

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

    这一部分主要就是判断need是否为空,然后选择相应的函数进行操作,不在做详细的叙述,下面是NeedEmptyToJson()的介绍。由于这一部分代码太长,所以相应的介绍在代码中进行注释说明。

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

  1 void NeedEmptyToJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, bool Enum_2_Str, bool Showzero)  2 {  3     const Descriptor* descriptor = msg.GetDescriptor();  
  4     const Reflection* reflection = msg.GetReflection(); 
  5     const uint count = descriptor->field_count();  //count为当前消息中所有的字段总数  6     uint judge = 0;//judge用来判断是否在当前json元素前加“,”用来分隔前后元素,如果judge==0,则不加,如果jugdge==1,则加“,”  7     std::string tmp_string;  //临时变量  8     std::int32_t v32=0;  9     std::uint32_t vu32=0; 10     std::int64_t v64=0; 11     std::uint64_t vu64=0; 12     double vd=0; 13     std::string str; 14     pb2jsonstring.append("{");  //添加第一个"{" 15     for (int it = 0; it <count; ++it) 
 16     {         
 17         const FieldDescriptor* goal_field=descriptor->field(it);  
 18         /*这里要用field()来取字段,因为field()是按字段的实际标号来取字段,而不是根据字段号来进行取字段,这样就避免的字段号不连续造成的某些字段取不到的问题。 */    19         if(nullptr==goal_field)  //不存在字段 20         { 21             continue; 22         } 
 23  24         if (goal_field->is_repeated())  //判断字段是否为repeated 25         {  
 26             if (reflection->FieldSize(msg, goal_field) > 0)  
 27             { 
 28                 tmp_string=""; 29                 tmp_string.append("\"").append(goal_field->name()).append("\":"); 30                 tmp_string .append("[");  //重复的字段用[]包围 31                 GetRepeatedJson(tmp_string, msg, goal_field, reflection, Enum_2_Str,Showzero); 
 32                 tmp_string.append("]"); 
 33                 judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);  
 34             } 35             continue;  
 36         } 37         switch (goal_field->type())  
 38         {  
 39         case FieldDescriptor::TYPE_MESSAGE:  
 40             {  
 41                 const Message& tmp_msg = reflection->GetMessage(msg, goal_field);  
 42                 if (0 != tmp_msg.ByteSize())  
 43                 { 
 44                     tmp_string=""; 45                     tmp_string.append("\"").append(goal_field->name()).append("\":"); 46                     NeedEmptyToJson(tmp_string,tmp_msg, Enum_2_Str, Showzero); 47                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 48                 }  
 49             }  
 50             break;  
 51              52         case FieldDescriptor::TYPE_INT32: 
 53             { 54                 v32=reflection->GetInt32(msg, goal_field); 55                 if(v32==0) 56                 { 57                     if(Showzero)   //字段值为0,也需要进行打印 58                     {                        
 59                         tmp_string=""; 60                         tmp_string.append("\"").append(goal_field->name()).append("\":"); 61                         tmp_string.append(std::to_string(v32)); //需要抓换成字符型 62                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
 63                     } 64                 } 65                 else 66                 { 67                     tmp_string=""; 68                     tmp_string.append("\"").append(goal_field->name()).append("\":"); 69                     tmp_string.append(std::to_string(v32));                     
 70                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
 71                 } 
 72             } 73             break;  
 74  75         case FieldDescriptor::TYPE_UINT32: 76             {  
 77                 vu32=reflection->GetUInt32(msg, goal_field); 78                 if(vu32==0) 79                 { 80                     if(Showzero) 81                     { 82                         tmp_string=""; 83                         tmp_string.append("\"").append(goal_field->name()).append("\":"); 84                         tmp_string.append(std::to_string(vu32));  
 85                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
 86                     } 87                 } 88                 else 89                 { 90                     tmp_string=""; 91                     tmp_string.append("\"").append(goal_field->name()).append("\":"); 92                     tmp_string.append(std::to_string(vu32)); 93                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
 94                 }       
 95              } 96             break;  
 97  98         case FieldDescriptor::TYPE_INT64:  
 99             {  
100                 v64=reflection->GetInt64(msg, goal_field);101                 if(v64==0)102                 {103                     if(Showzero)104                     {105                         tmp_string="";106                         tmp_string.append("\"").append(goal_field->name()).append("\":");         
107                         tmp_string.append(std::to_string(v64));108                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
109                     }110                 }111                 else112                 {113                     tmp_string="";114                     tmp_string.append("\"").append(goal_field->name()).append("\":");115                     tmp_string.append(std::to_string(v64));         
116                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);  
117                 } 
118             } 
119             break;  
120         case FieldDescriptor::TYPE_UINT64:  
121              {  
122                 vu64=reflection->GetUInt64(msg, goal_field);123                 if(vu64==0)124                 {125                     if(Showzero)126                     {127                         tmp_string="";                
128                         tmp_string.append("\"").append(goal_field->name()).append("\":");      
129                         tmp_string.append(std::to_string(vu64));130                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
131                     }132                 }133                 else134                 {135                     tmp_string="";                
136                     tmp_string.append("\"").append(goal_field->name()).append("\":");      
137                     tmp_string.append(std::to_string(vu64));138                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge); 
139                 }140              }

http://www.cnblogs.com/CLfei/p/7121737.html