问题描述
最近在使用http接口访问一个GRPC的服务时遇到一个数据类型转换的问题。一个时间戳字段在PB中定义的字段类型为uint64,返回到本地之后却是一个string类型,在我用uint64去接收这个字段时报了错。
原因分析
为什么GRPC要把int64转为string类型呢,他们的回答是遵循proto3的序列化规则,proto3的json-mapping中规定了int64/uint64/fixed64类型映射的json类型为string。如图:(PB文档地址:https://developers.google.com/protocol-buffers/docs/proto3#json)
很多人都质疑PB的这个行为,然而这并不能改变什么,下面是一个关于该问题的回答,大意就是:JS使用了52bit去实现IEEE754的双精度数,也就是说js在不丢失信息的情况下最大能表示的数是 2^52 。64位的数在JS中直接使用是会有问题了。PB为了客户端能正常处理数据而把64位数值直接转换为了string类型。
问题解决
本人使用的是golang语言,在处理http返回值时,使用jsonpb包代替了json包去解析返回的二进制数据。不过解析出来的是message格式的,用的时候还需要进一步加工处理,相比较与转换string类型到int64,感觉还是简单一点。
resp, err := http.Post(addr+path, "application/json", buf)
if err != nil {
t.Error(err)
} else {
if resp.Body != nil {
var result stat.ListDataRows_Response
err = jsonpb.Unmarshal(resp.Body, &result)
if err != nil {
t.Error(err)
} else {
t.Logf("result:%+v", result)
}
} else {
t.Log("result is nil")
}
}
返回值:
result:{
Rows:[
timestamp:1571195630000
tags:<key:"rule_id" value:"518852" >
values:<key:"logs" value:"*******" >
]
NextPageToken:1571195630000
}