方法介紹

    protobuf的介紹在這里就不詳細介紹了,主要是俺也是剛接觸,感興趣的同學可以去搜索相關博客或者直接去看源碼以及google的官方文檔(官方文檔表示很吃力)或者去這個網(wǎng)站:https://developers.google.com/protocol-buffers/docs/overview查看相應內容,這里面內容很全面,可以很方面的查詢各個函數(shù)的使用方法以及功能。本篇文章主要介紹一下本人最近做的一個protobuf轉json的小工具,下面進行拆分講解,完整的代碼在:git@github.com:chengfeiGitHub/P-bToJson.git。

    protobuf自帶一個MessageToJson()的函數(shù)可以將對應的消息轉換成json,一般情況下該函數(shù)可以滿足轉換需求。但是,最近項目的要求使用MessageToJson()無法實現(xiàn),主要要求是:

  1. 選擇特定的messge進行轉換(主要是提供包含需求字段號的set或者vector,根據(jù)提供的字段號進行轉換);

  2. 對于Enum類型的消息,可以選擇顯示枚舉名或者枚舉值;

  3. 對于字段值為0的字段,可以選擇顯示或者不顯示.

    主要有這三個要求,對于功能2、3現(xiàn)在最新的protobuf應該是支持的,但是沒有功能1的實現(xiàn)方式,所以只好自己寫一個小工具。

    說明:本工具由C++編寫完成

    首先是函數(shù)的聲明:

萬碼學堂,電腦培訓,計算機培訓,Java培訓,JavaEE開發(fā)培訓,青島軟件培訓,軟件工程師培訓

 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開發(fā)培訓,青島軟件培訓,軟件工程師培訓

 

    pb2jsonstring是存儲轉換結果的字符串,msg是需要轉換的消息,needs是需要轉換的字段號;函數(shù)GetRepeatedJson()是對重復的字段進行操作;NeedEmptyToJson()是當needs為空時對應的操作(needs為空表示需要轉換所有的字段);NeedNotEmptyToJson()是當needs不為空時對應的操作;AppendTmpStrign1()以及AppendTmpStrign2()是將臨時字符串添加到pb2jsonstring后的操作。

    上面的代碼保存到一個頭文件當中,就叫pbjsontest3.h吧,然后是pbjsontest3.cpp

    

萬碼學堂,電腦培訓,計算機培訓,Java培訓,JavaEE開發(fā)培訓,青島軟件培訓,軟件工程師培訓

 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開發(fā)培訓,青島軟件培訓,軟件工程師培訓

    這一部分主要就是判斷need是否為空,然后選擇相應的函數(shù)進行操作,不在做詳細的敘述,下面是NeedEmptyToJson()的介紹。由于這一部分代碼太長,所以相應的介紹在代碼中進行注釋說明。

萬碼學堂,電腦培訓,計算機培訓,Java培訓,JavaEE開發(fā)培訓,青島軟件培訓,軟件工程師培訓

  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為當前消息中所有的字段總數(shù)  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()是按字段的實際標號來取字段,而不是根據(jù)字段號來進行取字段,這樣就避免的字段號不連續(xù)造成的某些字段取不到的問題。 */    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