方法介紹
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),主要要求是:
選擇特定的messge進行轉換(主要是提供包含需求字段號的set或者vector,根據(jù)提供的字段號進行轉換);
對于Enum類型的消息,可以選擇顯示枚舉名或者枚舉值;
對于字段值為0的字段,可以選擇顯示或者不顯示.
主要有這三個要求,對于功能2、3現(xiàn)在最新的protobuf應該是支持的,但是沒有功能1的實現(xiàn)方式,所以只好自己寫一個小工具。
說明:本工具由C++編寫完成
首先是函數(shù)的聲明:
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);
pb2jsonstring是存儲轉換結果的字符串,msg是需要轉換的消息,needs是需要轉換的字段號;函數(shù)GetRepeatedJson()是對重復的字段進行操作;NeedEmptyToJson()是當needs為空時對應的操作(needs為空表示需要轉換所有的字段);NeedNotEmptyToJson()是當needs不為空時對應的操作;AppendTmpStrign1()以及AppendTmpStrign2()是將臨時字符串添加到pb2jsonstring后的操作。
上面的代碼保存到一個頭文件當中,就叫pbjsontest3.h吧,然后是pbjsontest3.cpp
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 }
這一部分主要就是判斷need是否為空,然后選擇相應的函數(shù)進行操作,不在做詳細的敘述,下面是NeedEmptyToJson()的介紹。由于這一部分代碼太長,所以相應的介紹在代碼中進行注釋說明。
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