上次写了一个Protobuf转Json的博文,实际本来是将那篇博文作为上,新写一篇博文作为下,即上为Protobuf转Json,下为Json转Protobuf。然而,上篇写的是使用的Json cpp作为三方的Json解析库,而我近期在项目中又没有再用到Json cpp。但正也因为在另外的项目帮忙,项目中使用了其他的Json解析库,并且该解析库使用C++11编写。我为了该项目的使用,重新封装了Json与Protobuf的互转,当然也使用了C++11的特性。因再抽空封装Json cpp与Protobuf的互转又稍显重复,因此总体就以此博文包含两个操作即可。
具体的源码可见我个人GitHub的地址:https://github.com/HaustWang/pb2json。
现就代码中的一些内容做一个简单的说明:
1. 代码中出现了使用using定义别名的方式,如下:
using Json = nlohmann::json;
这是c++11对于using添加的新的使用方法。该种使用等价于
typedef nlohmann::json Json;
3. 在Json与Protobuf互转的时候,采用了Protobuf里提供的反射机制。关于Google Protobuf反射的接口,可以参见:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message?hl=zh-cn。这些当然是属于google官网的,可能在国内比较难以看到。但只要在搜索"protobuf""反射"等关键字,还是可以搜索到很多相关的资料,比较推荐的是陈硕大神的。
4. 对于message里嵌套message结构,使用的递归实现,生成的Json属于Object嵌套Object
5. 对于message里出现的repeated字段,使用循环实现,生成的Json属于数组。
6. 在Json转message时,也同样依赖了message里字段的类型和是否为repeated字段来实现Json对象转message结构和数组转repeated
7. 这个代码中有两处地方可以改进:
1)对于重复的类型判断,可以使用宏的特性,定义宏实现。这样的话可以使用较少的代码实现同样的功能;并且在需要修改每一个的实现的时候可以减少代码的修改量,从而保证代码的高度一致性
2)该代码在Json转protobuf的时候,可以根据Json的各字段的属性以及Protobuf的反射机制的消息生成池去生成未命名的message结构。
============================================================华丽的分割线======================================================================
这篇博文是之前自己在实现Protobuf与Json互转的时候写的。因此该说明只针对使用Protobuf反射机制完成的代码的说明。
众所周知,反射是消耗性能的方式,虽然本人并未验证过Protobuf的反射机制的性能的问题。但针对这个问题,近期我个人实现了另外一个版本:生成代码的方式,具体代码详见上述提到的GitHub地址。不过该代码还未在项目中使用,即使使用时也只能作为附属工具。主要思想如下:
1. 通过解析proto文件,生成Ptotobuf与Json互转的头文件,头文件中针对每个Protobuf的message都提供两个静态函数ToJson(Protobuf的messge转Json)和ToMessage(Json转Protobuf)
2. 解析时先将proto文件中的定义字段分解为四个部分:字段规则(required, optional, repeated,其中repeated在Json中会是数组),字段类型(proto提供的基本类型, message类型, 枚举类型,其中message类型会对应Json的Object,Enum类型会对应为数字),字段名(该字段名会成为Json的元素key),函数后缀名(即字段名全部小写化,其主要目的是拼接Protobuf的函数的get/set函数。在protobuf中,无论字段名是否为大写或者小写,其对应的get/set函数的字段名全部为小写。