错误背景
使用github.com/grpc-ecosystem/grpc-gateway 库对grpc转http respnse 时,通过[github.com/golang/protobuf/jsonpb] 进行序列化,如果pb文件定义的字段采用int64 类型,则http response返回的字段类型会神奇的变为string。 序列化关键代码如下:
requestId := FromContext(ctx)
jpb := jsonpb.Marshaler{
OrigName: true,
EmitDefaults: true,
EnumsAsInts: true,
}
data, err := jpb.MarshalToString(p)// 序列化,该函数会将pb中int64转string
if err != nil {
return err
}
...
出错原因
github.com/golang/prot… 来自官方issue讨论如下: This matter has been considered in other PRs: #916 #286
The protobuf JSON mapping standard requires emission of in64 values as quoted strings, in order to work around a well known complication of the JSON standard that there is no guarantee or requirement of accuracy for numbers beyond those afforded by float64 type.
【翻译】protobuf JSON 映射标准要求将 in64 值作为带引号的字符串发出,以解决 JSON 标准的一个众所周知的复杂性,即除了 float64 类型提供的数字之外,无法保证或要求数字的准确性
大致意思是说,对于int64类型的字段,序列号json是复杂的,所以官方库并没有支持这种特性,只是简单的转化成了string类型输出。
解决方案
- 对于int类型字段,统一采用int32.这样可以正确response数字类型的字段了
- 或者像该commit一样,新增一些行为选项。帮助int64转int 。 github.com/golang/prot… 代码参考:
jpb := jsonpb.Marshaler{
OrigName: true,
EmitDefaults: true,
EnumsAsInts: true,
Int64AsInt: true// 通过该选项去控制类型
}
data, err := jpb.MarshalToString(p)
if err != nil {
return err
}
欢迎讨论
有任何问题欢迎私信或者加v(alanxiao1918)