业务要求返回json,但是服务内部使用的是proto协议,故需要将proto协议转为json格式。

先确定需求,我们要求的返回类型是 code, msg, data. 返回数据放在data里面。

 

这里方案总共有四种:

方案1:

  1. 下级服务返回protoData给网关,得到 []byte
  2. 根据[]byte解码proto结构, 直接解析到json返回结构体的Data成员变量
  3. 编码Json,返回数据

这个方案存在的问题就是说,json的编码会根据omitempty字段而不展示空的字段。

比如proto结构里面有默认字段,就不会展示,这种情况不满足需求。

 

方案2:

  1. 下级服务返回protoData给网关,得到 []byte
  2. 将下级服务返回的protoData解码,得到Proto数据结构
  3. 使用 jsonpb库,将Proto数据结构编码为Json字符串(叫它JsonData吧)。
  4. Json返回结构体的Data成员类型为 json.RawMessage,将JsonData赋值给Data成员变量
  5. 编码Json,返回数据

这里步骤3涉及到三个参数,满足了展示默认字段的需求。

但是相比方案2,它进行了三次数据结构的转换,一次数据copy。

 

方案3:

  1. 修改与下级服务通信proto文件,增加用于网关返回的结构体叫它JsonResponse
  2. 将下级服务传递的 []byte 直接解码到JsonResponse.Data成员变量上
  3. 将JsonResponse编码为json得到返回的[]byte, 返回数据

相比方案2,我们采用直接解码proto再编码proto为json的方案,减少了一次数据结构转化,一次数据Copy。

计算次数与方案1差不多,但是满足了默认字段展示的需求。

 

基于方案3,拓展方案4:

  1. 下级服务直接返回JsonResponse

这里我认为性能不如方案3,理由如下:

  1. 分析方案3,其实是[]byte->proto->json,两次转换
  2. 下级服务返回JsonResponse之后,我们还是要做[]byte->proto->json两次转换
  3. 下级服务返回的字段相比之前更多了,可以认为增加了网络开销
  4. 下级服务返回的结构体更大,编解码时耗时更多了

 

综上,我认为方案3是我们的最优解。

相比方案1在解决了后台提出的空字段不展示的问题的基础上,没有额外编解码性能开销。

 

代码如下:

 

ResponseProto就是 proto->json的过程

 

这里JsonResponse对象是这样定义的:

 

这样相当于每个请求多了一个结构,增加了代码量,但是减少了性能。

【golang】proto转json方案
Tagged on:     
0 0 vote
Article Rating
订阅
提醒
0 评论
Inline Feedbacks
View all comments