本篇文章主要介绍如何通过静态or动态proto schema,校验json并转换成buffer;读取buffer转换成可读性的json格式。
依赖库
vite@2.9.9
vue@2.6.11
mqtt@4.1.0
protobufjs~6.11.3
protobufjs使用参考文档:febeacon.com/protobuf_do…
安装protobufjs
npm install protobufjs [--save --save-prefix=~]
静态.proto文件转成.js文件
- 在src下新建proto目录,将.proto文件放进去
- 在
package.json里定义命令,该命令会将.proto文件转换.js文件
"proto": "pbjs -t json-module -w es6 -o src/proto/proto.js src/proto/transport.proto" - 执行
npm run proto命令,会发现proto目录下会生成proto.js文件
引入protobufjs
import protobuf from "protobufjs";
引入转换后的proto.js文件
import protoRoot from "../../proto/proto.js";
根据静态.proto文件,buffer和json互相转换
将buffer转成json(根据proto schema)
.proto案例
syntax = "proto3";
package transport;
message ToServerRpcResponseMsg {
int32 requestId = 1;
string payload = 2;
string error = 3;
}
转换方法
// 此处message需要传入buffer格式
function getJSON(message) {
let msg = ""
const MyMessage = protoRoot.lookup("transport.ToServerRpcResponseMsg");
if (!MyMessage) {
msg = "";
}
try {
const decodedMessage = MyMessage.decode(message);
msg = JSON.stringify(decodedMessage);
} catch (e) {
console.log("e", e);
}
return msg;
}
校验json并转成buffer(根据proto schema)
.proto案例
syntax = "proto3";
package transportapi;
message RpcRequest {
string method = 1;
string params = 2;
}
转换方法
// 此处payload需要是json格式
function toProtobufBuffer(payload) {
const MyMessage = protoRoot.lookup("transportapi.RpcRequest");
if (errMsg) {
Message.error("内容格式不正确。");
return null;
}
const req = MyMessage.create(JSON.parse(payload));
const buffer = MyMessage.encode(req).finish();
if (!buffer.length) {
// 若不符合proto规则定义,转换出来则是空
Message.error("内容格式不正确。");
return null;
}
return buffer;
}
根据动态proto schema,buffer和json互相转换
import protobuf from "protobufjs";
// 入参是动态proto schema,返回值是可操作的MyMessage,拿到MyMessage后,操作和静态一样。
function getMyMessage(proto) {
const root = protobuf.parse(proto, { keepCase: true }).root;
// 找出类型名称typeName
let typeName = "";
traverseTypes(
root,
type => {
typeName = type.fullName.substr(1, type.fullName.length - 1); // 此方法可根据定义的schema做响应调整
},
0
);
const MyMessage = root.lookup(typeName);
if (!MyMessage) {
// 定义的proto schema格式不正确。
return null;
}
return MyMessage;
}
function traverseTypes(current, fn, count) {
if (count === 2) {
// 取出package和最外面的message
fn(current);
}
if (current.nestedArray)
current.nestedArray.forEach(function (nested) {
traverseTypes(nested, fn, count + 1);
});
}
使用vite打包后异常
参考issue:github.com/vitejs/vite…
使用vite打包构建后,页面渲染异常,但没有具体的报错信息
解决方式:通过在vite.config.js里定义别名
defineConfig({
resolve: {
alias: [
{
find: new RegExp("protobufjs/light$"),
replacement: "protobufjs/dist/light/protobuf.min.js"
},
{
find: new RegExp("protobufjs/minimal$"),
replacement: "protobufjs/dist/minimal/protobuf.min.js"
},
{
find: new RegExp("protobufjs$"),
replacement: "protobufjs/dist/protobuf.min.js"
}
]
}
})