在和第三方對接時(shí)倦西,對方要求使用protobuf協(xié)議,實(shí)現(xiàn)數(shù)據(jù)序列化進(jìn)行傳輸旅急。協(xié)議文件使用了兩個(gè)逢勾,因?yàn)槭乔短最愋偷摹5亲罱K放棄了藐吮,因?yàn)樵谑褂弥Ц秾毜男〕绦蜷_發(fā)時(shí)溺拱,對方接收到的數(shù)據(jù)和我發(fā)給他的是不一樣的。
但是怎么說是成功了的谣辞。以下是看了很多文檔資料實(shí)踐做的總結(jié)迫摔。
github 項(xiàng)目 https://github.com/Zhang19910325/protoBufferForWechat 介紹了如何使用protobuf。以下是開發(fā)時(shí)遇到的問題和解決方法泥从。
- github 項(xiàng)目 https://github.com/Zhang19910325/protoBufferForWechat 句占,將其下載放進(jìn)小程序目錄下
- windows環(huán)境執(zhí)行以下命令
npm install -g protobufjs - awesome.proto 文件進(jìn)行處理 ( 處理為json )
在控制臺執(zhí)行命令:pbjs -t json awesome.proto > awesome.json (確保是在同一個(gè)根目錄下)
將生成的 協(xié)議.json 第一行添加 “ module.exports = ” 如:
module.exports = {
"nested": {
"UniversalReportRequest": {
"fields": {
"awesomeField": {
"type": "隨便加的",
"id": 1
}
}
},
"'AdIdInfo'": {
"fields": {
"awesomeField": {
"type": "隨便加的",
"id": 1
}
}
}
}
};
- 序列化要做的事情
let protobuf = require('../../weichatPb/protobuf.js'); //引入protobuf模塊(下載的那個(gè)文件)
let UniversalReportRequest = require('../../awesome.js'); //加載awesome.proto對應(yīng)的js
//序列化要用到的
let AwesomeRootUni = protobuf.Root.fromJSON(UniversalReportRequest);
let LoginRequestInfo = AwesomeRootUni.lookupType('AdIdInfo');
let LoginRequestUni = AwesomeRootUni.lookupType('UniversalReportRequest');
- 先序列化內(nèi)嵌的數(shù)據(jù)
let adIdInfoAll = {
creativeId: boftupAll.creative_id,
taskId: boftupAll.task_id
};
//將adIdInfoAll序列化轉(zhuǎn)為二進(jìn)制
let messageInfo = LoginRequestInfo.create(adIdInfoAll);
let bufferInfo = LoginRequestInfo.encode(messageInfo).finish(); //內(nèi)嵌數(shù)序列化的結(jié)果
- 將序列化的數(shù)據(jù)塞進(jìn)最外層的數(shù)據(jù)后躯嫉,再次序列化
let boftupXuyaode = {
id: this.data.boftuId,
timestamp: this.data.boftup.timestamp,
adIdInfoAll:{
bufferInfo, //內(nèi)嵌數(shù)據(jù)序列化的結(jié)果
}
},
- 將boftupXuyaode序列化
let messageUni = LoginRequestUni.create(boftupXuyaode );// 將對象序列化成請求體實(shí)例
let bufferUni = LoginRequestUni.encode(messageUni).finish()
- 以上就是內(nèi)嵌的數(shù)據(jù)序列化辖众。最終得bufferUni就是所有序列化后得結(jié)果了。但是和敬,還沒結(jié)束凹炸。以上所打印出來得數(shù)據(jù)有的是大于127位的。而java中byte類型數(shù)據(jù)取值范圍為-128~127昼弟。所以還要在每次的序列化之后使用 JS Byte數(shù)據(jù)字轉(zhuǎn)字節(jié)(無符號轉(zhuǎn)有符號)
function unsigned2signed(unsigned) {
var value = parseInt(unsigned, 10);
if (value > 256)
return value % 256;
var temp = []; //10進(jìn)制轉(zhuǎn)換為2進(jìn)制字符串
while (value > 0) {
if (value % 2 != 0) {
temp.push(1);
} else {
temp.push(0);
}
value = parseInt(value / 2);
}
//不足8位再前方做補(bǔ)0操作
temp.reverse();
while (temp.length < 8) {
temp.unshift(0)
}
temp = temp.join('');
var signed = ''; //無符號轉(zhuǎn)有符號字節(jié) 取該二進(jìn)制字符串補(bǔ)碼即可
if (temp.substr(0, 1) == 1) { //二進(jìn)制符號位等于1 則有符號
for (var i = 1; i < temp.length; i++) {
temp.substr(i, 1) == 1 ? signed += 0 : signed += 1;
}
return ('-' + (parseInt(signed, 2) + 1));
} else {
for (var i = 0; i < temp.length; i++) {
signed += temp.substr(i, 1); //源碼輸出
}
return (parseInt(signed, 2));
}
}
- 無符號轉(zhuǎn)有符號的時(shí)候要用循環(huán)便利一下~
var array = Array.from(bufferInfo)
let arrNumberString = [];
for(let i=0;i<array.length; i++){
let unsignedString1 = Number(this.unsigned2signed(array[i]));
arrNumberString.push(unsignedString)
} //arrNumberString 最終 java 可以解析成功了啤它!