問題描述
最近在使用http接口訪問一個GRPC的服務(wù)時遇到一個數(shù)據(jù)類型轉(zhuǎn)換的問題猜嘱。一個時間戳字段在PB中定義的字段類型為uint64,返回到本地之后卻是一個string類型蕴侧,在我用uint64去接收這個字段時報了錯。
原因分析
為什么GRPC要把int64轉(zhuǎn)為string類型呢两入,他們的回答是遵循proto3的序列化規(guī)則,proto3的json-mapping中規(guī)定了int64/uint64/fixed64類型映射的json類型為string敲才。如圖:(PB文檔地址:https://developers.google.com/protocol-buffers/docs/proto3#json)
pb-josnMapping.jpg
很多人都質(zhì)疑PB的這個行為裹纳,然而這并不能改變什么,下面是一個關(guān)于該問題的回答紧武,大意就是:JS使用了52bit去實現(xiàn)IEEE754的雙精度數(shù)剃氧,也就是說js在不丟失信息的情況下最大能表示的數(shù)是 2^52 。64位的數(shù)在JS中直接使用是會有問題了阻星。PB為了客戶端能正常處理數(shù)據(jù)而把64位數(shù)值直接轉(zhuǎn)換為了string類型朋鞍。
int64tostring-reasopn.jpg
問題解決
本人使用的是golang語言,在處理http返回值時妥箕,使用jsonpb包代替了json包去解析返回的二進制數(shù)據(jù)滥酥。不過解析出來的是message格式的,用的時候還需要進一步加工處理畦幢,相比較與轉(zhuǎn)換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
}