protobuf转json

方法介绍

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

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

  1. 选择特定的messge进行转换(主要是提供包含需求字段号的set或者vector,根据提供的字段号进行转换);
  2. 对于Enum类型的消息,可以选择显示枚举名或者枚举值;
  3. 对于字段值为0的字段,可以选择显示或者不显示.

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

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

首先是函数的声明:

 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是需要转换的字段号;函数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为空,表示需要将所有的字段转换为json
16     {
17         NeedEmptyToJson(pb2jsonstring, msg, Enum_2_Str, Showzero);
18     }
19     else
20     {
21         NeedNotEmptyToJson(pb2jsonstring, msg, need, Enum_2_Str, Showzero);
22     }
23 }

这一部分主要就是判断need是否为空,然后选择相应的函数进行操作,不在做详细的叙述,下面是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为当前消息中所有的字段总数
  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                 else
112                 {
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                 else
134                 {
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              }
141             break;
142         case FieldDescriptor::TYPE_STRING:
143         case FieldDescriptor::TYPE_BYTES:
144             {
145
146                 str=reflection->GetString(msg, goal_field);
147                 if(str.empty())
148                 {
149                     if(Showzero)
150                     {
151                         tmp_string="";
152                         tmp_string.append("\"").append(goal_field->name()).append("\":");
153                         tmp_string.append("\"").append(str).append("\"");
154                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
155                     }
156                 }
157                 else
158                 {
159                     tmp_string="";
160                     tmp_string.append("\"").append(goal_field->name()).append("\":");
161                     tmp_string.append("\"").append(str).append("\"");
162                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
163
164                 }
165             }
166             break;
167         case FieldDescriptor::TYPE_DOUBLE:
168             {
169                 vd=reflection->GetDouble(msg, goal_field);
170                 if(vd==0)
171                 {
172                     if(Showzero)
173                     {
174                         tmp_string="";
175                         tmp_string.append("\"").append(goal_field->name()).append("\":");
176                         tmp_string.append(std::to_string(vd));
177                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
178                     }
179                 }
180                 else
181                 {
182                     tmp_string="";
183                     tmp_string.append("\"").append(goal_field->name()).append("\":");
184                     tmp_string.append(std::to_string(vd));
185                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
186                 }
187             }
188             break;
189         case FieldDescriptor::TYPE_BOOL:
190             {
191                 tmp_string="";
192                 tmp_string.append("\"").append(goal_field->name()).append("\":");
193                 if (reflection->GetBool(msg, goal_field))
194                     tmp_string.append("true");
195                 else
196                     tmp_string.append("false");
197                 judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
198
199             }
200             break;
201         case FieldDescriptor::TYPE_ENUM:
202             {
203                 tmp_string="";
204                 tmp_string.append("\"").append(goal_field->name()).append("\":");
205                 if (Enum_2_Str) //判断显示枚举名还是枚举值
206                 {
207                     tmp_string.append("\"").append(reflection->GetEnum(msg,goal_field)->name()).append("\"");
208                 }
209                 else
210                 {
211                     static char enumstr[8];
212                     memset(enumstr, 0, sizeof(enumstr));
213                     snprintf(enumstr, sizeof(enumstr), "%d", reflection->GetEnum(msg,goal_field)->number());
214                     tmp_string.append(enumstr);
215                 }
216                 judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
217             }
218             break;
219         default:
220             break;
221         }
222     }
223     pb2jsonstring.append("}");
224 }
225
226 int AppendTmpString1(std::string &pb2jsonstring,std::string &tmp_string, int judge)
227 {
228     if ( judge!=0 && tmp_string.length()!=0)
229     {
230         pb2jsonstring.append(",").append(tmp_string);
231         return judge;
232     }
233     else if(judge==0 && tmp_string.length()!=0)
234     {
235         pb2jsonstring.append(tmp_string);
236         return 1;
237     }
238     return judge;
239 }

下面need不为空时候的转换:

  1 void NeedNotEmptyToJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, std::vector<uint>& needs, bool Enum_2_Str, bool Showzero)
  2 {
  3     const Descriptor* descriptor = msg.GetDescriptor();
  4     const Reflection* reflection = msg.GetReflection();
  5
  6     uint judge = 0;
  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
 15     pb2jsonstring.append("{");
 16
 17     for (auto it=needs.begin(); it != needs.end(); ++it)
 18     {
 19         const FieldDescriptor* goal_field=descriptor->FindFieldByNumber(*it);
 20         //need为空的转换和不为空的几乎一样,主要差别是对字段的提取,不为空时需要使用FindFieldByNumber()来进行操作,这样可以取任意字段号对应的字段。将need为空和不为空分开写主要是测试中这样可以节省时间,其实是可以写到一块的,有兴趣的同学可以进行修改。
 21
 22         if(nullptr==goal_field)  //不存在字段
 23         {
 24             continue;
 25         }
 26
 27         if (goal_field->is_repeated())
 28         {
 29             if (reflection->FieldSize(msg, goal_field) > 0)
 30             {
 31                 tmp_string="";
 32                 tmp_string.append("\"").append(goal_field->name()).append("\":");
 33                 tmp_string .append("[");
 34                 GetRepeatedJson(tmp_string, msg, goal_field, reflection, Enum_2_Str,Showzero);
 35                 tmp_string.append("]");
 36                 judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 37             }
 38             continue;
 39         }
 40         switch (goal_field->type())
 41         {
 42         case FieldDescriptor::TYPE_MESSAGE:
 43             {
 44                 const Message& tmp_msg = reflection->GetMessage(msg, goal_field);
 45                 if (0 != tmp_msg.ByteSize())
 46                 {
 47                     tmp_string="";
 48                     tmp_string.append("\"").append(goal_field->name()).append("\":");
 49                     NeedEmptyToJson(tmp_string,tmp_msg, Enum_2_Str, Showzero);
 50                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 51                 }
 52             }
 53             break;
 54
 55         case FieldDescriptor::TYPE_INT32:
 56             {
 57                 v32=reflection->GetInt32(msg, goal_field);
 58                 if(v32==0)
 59                 {
 60                     if(Showzero)   //字段值为0,也需要进行打印
 61                     {
 62                         tmp_string="";
 63                         tmp_string.append("\"").append(goal_field->name()).append("\":");
 64                         tmp_string.append(std::to_string(v32));
 65                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 66                     }
 67                 }
 68                 else
 69                 {
 70                     tmp_string="";
 71                     tmp_string.append("\"").append(goal_field->name()).append("\":");
 72                     tmp_string.append(std::to_string(v32));
 73                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 74                 }
 75             }
 76             break;
 77
 78         case FieldDescriptor::TYPE_UINT32:
 79             {
 80                 vu32=reflection->GetUInt32(msg, goal_field);
 81                 if(vu32==0)
 82                 {
 83                     if(Showzero)
 84                     {
 85                         tmp_string="";
 86                         tmp_string.append("\"").append(goal_field->name()).append("\":");
 87                         tmp_string.append(std::to_string(vu32));
 88                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 89                     }
 90                 }
 91                 else
 92                 {
 93                     tmp_string="";
 94                     tmp_string.append("\"").append(goal_field->name()).append("\":");
 95                     tmp_string.append(std::to_string(vu32));
 96                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 97                 }
 98              }
 99             break;
100
101         case FieldDescriptor::TYPE_INT64:
102             {
103                 v64=reflection->GetInt64(msg, goal_field);
104                 if(v64==0)
105                 {
106                     if(Showzero)
107                     {
108                         tmp_string="";
109                         tmp_string.append("\"").append(goal_field->name()).append("\":");
110                         tmp_string.append(std::to_string(v64));
111                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
112                     }
113                 }
114                 else
115                 {
116                     tmp_string="";
117                     tmp_string.append("\"").append(goal_field->name()).append("\":");
118                     tmp_string.append(std::to_string(v64));
119                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
120                 }
121             }
122             break;
123         case FieldDescriptor::TYPE_UINT64:
124              {
125                 vu64=reflection->GetUInt64(msg, goal_field);
126                 if(vu64==0)
127                 {
128                     if(Showzero)
129                     {
130                         tmp_string="";
131                         tmp_string.append("\"").append(goal_field->name()).append("\":");
132                         tmp_string.append(std::to_string(vu64));
133                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
134                     }
135                 }
136                 else
137                 {
138                     tmp_string="";
139                     tmp_string.append("\"").append(goal_field->name()).append("\":");
140                     tmp_string.append(std::to_string(vu64));
141                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
142                 }
143              }
144             break;
145         case FieldDescriptor::TYPE_STRING:
146         case FieldDescriptor::TYPE_BYTES:
147             {
148
149                 str=reflection->GetString(msg, goal_field);
150                 if(str.empty())
151                 {
152                     if(Showzero)
153                     {
154                         tmp_string="";
155                         tmp_string.append("\"").append(goal_field->name()).append("\":");
156                         tmp_string.append("\"").append(str).append("\"");
157                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
158                     }
159                 }
160                 else
161                 {
162                     tmp_string="";
163                     tmp_string.append("\"").append(goal_field->name()).append("\":");
164                     tmp_string.append("\"").append(str).append("\"");
165                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
166
167                 }
168             }
169             break;
170         case FieldDescriptor::TYPE_DOUBLE:
171             {
172                 vd=reflection->GetDouble(msg, goal_field);
173                 if(vd==0)
174                 {
175                     if(Showzero)
176                     {
177                         tmp_string="";
178                         tmp_string.append("\"").append(goal_field->name()).append("\":");
179                         tmp_string.append(std::to_string(vd));
180                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
181                     }
182                 }
183                 else
184                 {
185                     tmp_string="";
186                     tmp_string.append("\"").append(goal_field->name()).append("\":");
187                     tmp_string.append(std::to_string(vd));
188                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
189                 }
190             }
191             break;
192         case FieldDescriptor::TYPE_BOOL:
193             {
194                 tmp_string="";
195                 tmp_string.append("\"").append(goal_field->name()).append("\":");
196                 if (reflection->GetBool(msg, goal_field))
197                     tmp_string.append("true");
198                 else
199                     tmp_string.append("false");
200                 judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
201
202             }
203             break;
204         case FieldDescriptor::TYPE_ENUM:
205             {
206                 tmp_string="";
207                 tmp_string.append("\"").append(goal_field->name()).append("\":");
208                 if (Enum_2_Str)
209                 {
210                     tmp_string.append("\"").append(reflection->GetEnum(msg,goal_field)->name()).append("\"");
211                 }
212                 else
213                 {
214                     static char enumstr[8];
215                     memset(enumstr, 0, sizeof(enumstr));
216                     snprintf(enumstr, sizeof(enumstr), "%d", reflection->GetEnum(msg,goal_field)->number());
217                     tmp_string.append(enumstr);
218                 }
219                 judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
220             }
221             break;
222         default:
223             break;
224         }
225     }
226     pb2jsonstring.append("}");
227 }

然后就是需要对repeated的字段进行相应的转换,

  1 void GetRepeatedJson(std::string& pb2jsonstring, const ::google::protobuf::Message& msg, const google::protobuf::FieldDescriptor *goal_field, const ::google::protobuf::Reflection *reflection, bool Enum_2_Str,bool Showzero)
  2 {
  3     std::string tmp_string;
  4     int judge=0;
  5     std::int32_t v32=0;
  6     std::uint32_t vu32=0;
  7     std::int64_t v64=0;
  8     std::uint64_t vu64=0;
  9     double vd=0;
 10     std::string str;
 11     for (int i = 0; i < reflection->FieldSize(msg, goal_field); ++i)
 12     {
 13         switch (goal_field->type())
 14         {
 15         case FieldDescriptor::TYPE_MESSAGE:
 16             {
 17                 const Message& tmp_msg = reflection->GetRepeatedMessage(msg, goal_field, i);
 18                 if (0 != tmp_msg.ByteSize())
 19                 {
 20                     tmp_string="";
 21                     //当重复的是message时,需要全部进行转换,不需要选择特定的字段进行转换,当然有这个需求的也可以进行相应的改进,不过会麻烦一些。重复字段的提取主要就是Get方式的不同,这个可以查阅文章开头中提到的文档,里面有详细说明
 22                     NeedEmptyToJson(tmp_string, tmp_msg, Enum_2_Str,Showzero);
 23                     judge = AppendTmpString2(pb2jsonstring,tmp_string,judge);
 24                 }
 25             }
 26             break;
 27         case FieldDescriptor::TYPE_INT32:
 28             {
 29                 v32=reflection->GetRepeatedInt32(msg, goal_field,i);
 30                 if(v32==0)
 31                 {
 32                     if(Showzero)
 33                     {
 34                         tmp_string="";
 35                         tmp_string.append(std::to_string(v32));
 36                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 37                     }
 38                 }
 39                 else
 40                 {
 41                     tmp_string="";
 42                     tmp_string.append(std::to_string(v32));
 43                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 44                 }
 45             }
 46
 47             break;
 48         case FieldDescriptor::TYPE_UINT32:
 49             {
 50                 vu32=reflection->GetRepeatedUInt32(msg, goal_field,i);
 51                 if(vu32==0)
 52                 {
 53                     if(Showzero)
 54                     {
 55                         tmp_string="";
 56                         tmp_string.append(std::to_string(vu32));
 57                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 58                     }
 59                 }
 60                 else
 61                 {
 62                     tmp_string="";
 63                     tmp_string.append(std::to_string(vu32));
 64                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 65                 }
 66              }
 67             break;
 68         case FieldDescriptor::TYPE_INT64:
 69             {
 70                 v64=reflection->GetRepeatedInt64(msg, goal_field,i);
 71                 if(v64==0)
 72                 {
 73                     if(Showzero)
 74                     {
 75                         tmp_string="";
 76                         tmp_string.append(std::to_string(v64));
 77                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 78                     }
 79                 }
 80                 else
 81                 {
 82                     tmp_string="";
 83                     tmp_string.append(std::to_string(v64));
 84                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 85                 }
 86             }
 87             break;
 88         case FieldDescriptor::TYPE_UINT64:
 89             {
 90                 vu64=reflection->GetRepeatedUInt64(msg, goal_field,i);
 91                 if(vu64==0)
 92                 {
 93                     if(Showzero)
 94                     {
 95                         tmp_string="";
 96                         tmp_string.append(std::to_string(vu64));
 97                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
 98                     }
 99                 }
100                 else
101                 {
102                     tmp_string="";
103                     tmp_string.append(std::to_string(vu64));
104                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
105                 }
106
107             }
108             break;
109         case FieldDescriptor::TYPE_STRING:
110         case FieldDescriptor::TYPE_BYTES:
111             {
112                 str="";
113                 str=reflection->GetRepeatedString(msg, goal_field,i);
114                 if(str.empty())
115                 {
116                     if(Showzero)
117                     {
118                         tmp_string="";
119                         tmp_string.append("\"").append(str).append("\"");
120                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
121                     }
122                 }
123                 else
124                 {
125                     tmp_string="";
126                     tmp_string.append("\"").append(str).append("\"");
127                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
128
129                 }
130             }
131             break;
132         case FieldDescriptor::TYPE_DOUBLE:
133             {
134                 vd=reflection->GetRepeatedDouble(msg, goal_field,i);
135                 if(vd==0)
136                 {
137                     if(Showzero)
138                     {
139                         tmp_string="";
140                         tmp_string.append(std::to_string(vd));
141                         judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
142                     }
143                 }
144                 else
145                 {
146                     tmp_string="";
147                     tmp_string.append(std::to_string(vd));
148                     judge = AppendTmpString1(pb2jsonstring,tmp_string,judge);
149                 }
150
151             }
152             break;
153          case FieldDescriptor::TYPE_BOOL:
154         {
155             tmp_string="";
156             if(reflection->GetRepeatedBool(msg, goal_field,i))
157                 tmp_string.append("true");
158             else
159                 tmp_string.append("false");
160             judge = AppendTmpString2(pb2jsonstring,tmp_string,judge);
161
162         }
163         break;
164         case FieldDescriptor::TYPE_ENUM:
165             {
166                tmp_string="";
167                if (Enum_2_Str)
168                     {
169                         tmp_string.append("\"").append(reflection->GetRepeatedEnum(msg,goal_field,i)->name()).append("\"");
170                     }
171                 else
172                     {
173                         static char enumstr[8];
174                         memset(enumstr, 0, sizeof(enumstr));
175                         snprintf(enumstr, sizeof(enumstr), "%d", reflection->GetRepeatedEnum(msg,goal_field,i)->number());
176                         tmp_string.append(enumstr);
177                     }
178                 judge = AppendTmpString2(pb2jsonstring,tmp_string,judge);
179             }
180             break;
181         default:
182             break;
183         }
184     }
185 }
186 int AppendTmpString2(std::string &pb2jsonstring,std::string &tmp_string, int judge)
187 {
188     if( judge!=0 && tmp_string.length()!=0)
189     {
190         pb2jsonstring.append(",").append(tmp_string);
191         return judge;
192     }
193     else if( judge==0 && tmp_string.length()!=0)
194     {
195         pb2jsonstring.append(tmp_string);
196         return 1;
197     }
198     return judge;
199 }

总结说明

本文中介绍的方法从逻辑上来说没有什么特别的地方,就是读取字段名,字段值然后添加到对应的字符串当中,代码比较繁琐,还有很大的改进空间,后来使用宏定义的##操作减少了很多代码量,比如GetInt()与GetRepeatedInt()可以通过使用“##”操作合并到一个函数中进行操作。

文中有不合理的地方希望各位批评指正。

时间: 2024-11-05 20:43:55

protobuf转json的相关文章

protobuf与json转换

protobuf对象不能直接使用jsonlib去转,因为protobuf生成的对象的get方法返回的类型有byte[],而只有String类型可以作为json的key,protobuf提供方法进行转换. 引用maven依赖: <dependency> <groupId>com.googlecode.protobuf-java-format</groupId> <artifactId>protobuf-java-format</artifactId>

protobuf的简单应用,json和protocol Buffer的转换简单例子

Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它可用于通讯协议.数据存储等领域的语言无关.平台无关.可扩展的序列化结构数据格式.目前提供了 C++.Java.Python 三种语言的 API. 简介 什么是 Google Protocol Buffer? 假如您在网上搜索,应该会得到类似这样的文字介绍: Google Protocol Buffe

C结构体与Json字符串自动转换

我们知道在Java中利用Gson这个包可以很方便地将Object和Json进行自动转换(串行化/反串行化).其原理是利用了Java的反射机制. 最近我的项目中需要将C结构体与Json自动互转.项目背景其实是一个类似protobuf的json协议生成与解析,协议很多,所以我们肯定是希望从一个C结构体的对象自动转成Json,不然协议一条一条自己写,手筋要累断. 要实现这个需求,首先就要给C结构体加入反射机制.我的处理方法是让用户在定义结构体时,额外再定义一个metainfo,用于保存这个结构体的反射

Protobuf的简单介绍、使用和分析

Protobuf的简单介绍.使用和分析   一.protobuf是什么? protobuf(Google Protocol Buffers)是Google提供一个具有高效的协议数据交换格式工具库(类似Json),但相比于Json,Protobuf有更高的转化效率,时间效率和空间效率都是JSON的3-5倍.后面将会有简单的demo对于这两种格式的数据转化效率的对比.但这个库目前使用还不是太流行,据说谷歌内部很多产品都有使用. 二.protobuf有什么? Protobuf 提供了C++.java.

golang Protobuf学习

protobuf是一种高效的数据传输格式(Google's data interchange format),且与语言无关,protobuf和json是基于http服务中最常见的两种数据格式.今天来学习基于golang的protobuf相关内容. google protocol buffer: https://developers.google.com/protocol-buffers/golang 官方提供的protobuf支持插件:https://github.com/golang/prot

Swoole http server + yaf, swoole socket server + protobuf 等小结

拥抱swoole, 拥抱更好的php Swoole 是什么? Yaf 是什么? 接触swoole已经4年多了,一直没有好好静下心来学习.一直在做web端的应用,对网络协议和常驻内存型服务器一窍不通.一不留神swoole已经从小众扩展变成了流行框架,再不学习就完了 swoole + yaf swoole server 的角色 还是先用swoole来做一个http server. 常见的php web应用,通常是apache+fast-cgi 或者 nginx + php-fpm.这里以php-fp

修改现有消息类让.net core项目支持Protobuf - 【无需使用 [ProtoBuf.ProtoContract] 的方法】

前言 第二次发博客,希望大家多多鼓励!!! 又接无上老板的一个需求,需要让.net core消息发送端跟消息接收端通信的消息是protobuf格式的(基于protobuf比json小一倍数据量,独特的编码.没有fieldname等),但现有项目的消息类数量巨多,按照网上的方案是安装protobuf.net 这个nuget包,然后需要给消息类一个一个添加[ProtoBuf.ProtoContract].[ProtoBuf.ProtoMember(index)]等Attributes,更可悲的是,还

app服务器

http://heipark.iteye.com/blog/1847421http://heipark.iteye.com/blog/1847421http://wenku.baidu.com/view/f761cc1f55270722192ef769.html 服务框架:1.servlet2.netty协议:1.http 1.02.http 1.1db:mysql就可以了ORM框架:mybatis缓存:redis 技术:网络通信: tcp,http等:Web服务:servlet, cgi脚本,

Java8 Lambda表达应用 -- 单线程游戏server+异步数据库操作

前段时间我们游戏server升级到开发环境Java8,这些天,我再次server的线程模型再次设计了一下,耗费Lambda表情. LambdaJava代码.特别是丑陋不堪的匿名内部类,这篇文章主要就是想和大家分享这一点. 线程模型 首先简介一下我们游戏server的线程模型.大致例如以下图所看到的: Netty线程池仅仅处理消息的收发,当Netty收到消息之后.会交给游戏逻辑线程处理.因为是单线程在处理游戏逻辑,所以每个消息必须非常快处理完.也就是说,不能有数据库等耗时操作.不然逻辑线程非常可能