介绍
ProtoBuf(protocol buffers) 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。,是一种灵活,高效,自动化机制的结构数据序列化方法比XML更小,更快,更为简单。
本项目主要是OpenHarmony系统下以 protobuf.js 5.0.3 为主要依赖开发,主要接口针对OpenHarmony系统进行合理的适配研发。
下载安装
1.安装
ohpm install @ohos/protobufjs
2.在需要使用的页面导入protobuf
import protobuf from '@ohos/protobufjs'
使用说明
protobuf支持的输入格式
1.proto格式字符串
const protoStr = 'syntax = "proto3"; package com.user;message UserLoginResponse{string sessionId = 1;string userPrivilege = 2;bool isTokenType = 3;string formatTimestamp = 4;}';
2.proto文件映射的json字符串
const protoJson = '{
"package": "com.user",
"messages": [
{
"name": "UserLoginResponse",
"fields": [
{
"rule": "optional",
"type": "string",
"name": "sessionId",
"id": 1
},
{
"rule": "optional",
"type": "string",
"name": "userPrivilege",
"id": 2
},
{
"rule": "optional",
"type": "bool",
"name": "isTokenType",
"id": 3
},
{
"rule": "optional",
"type": "string",
"name": "formatTimestamp",
"id": 4
}
]
}
]
}'
3.proto文件
在resource->rawfile文件夹下按照 .proto文件格式定义消息体结构,如:userproto.proto文件。
syntax = "proto3";
package com.user;
message UserLoginResponse{
string sessionId = 1;
string userPrivilege = 2;
bool isTokenType = 3;
string formatTimestamp = 4;
}
4.json文件
在resource->rawfile文件夹下存放proto文件映射的json文件,参照第二点。
对象编解码
1.在resource->rawfile文件夹下按照 .proto文件格式定义消息体结构,如:userproto.proto文件。
syntax = "proto3";
package com.user;
message UserLoginResponse{
string sessionId = 1;
string userPrivilege = 2;
bool isTokenType = 3;
string formatTimestamp = 4;
}
2.读取.proto 文件
let builder = await Protobuf.loadProtoFile("userproto.proto", null, null, getContext(this).resourceManager)
3.对象编码
// 构建消息体
var UserLoginResponse = builder.build("com.user.UserLoginResponse");
let userLoginData = {
sessionId: "testAsynchronouslyLoadProtoFile",
userPrivilege: "John123",
isTokenType: false,
formatTimestamp: "12342222"
};
// 对象编码的两种方式
// 方式一:通过消息体静态编码方法进行编码
var arrayBuffer = UserLoginResponse.encode(userLoginData).toArrayBuffer();
// 方式二:通过消息体实例进行编解码
var msg = new UserLoginResponse(userLoginData);
var arrayBuffer = msg.toArrayBuffer();
4.对象解码
let decode = UserLoginResponse.decode(arrayBuffer)
主要接口示例:
1.proto字符串编解码
Button("proto字符串编解码")
.width('80%')
.type(ButtonType.Capsule)
.backgroundColor('#0D9FFB')
.onClick(async () => {
try {
// 1.创建protbuf.Builder对象:用于构造协议消息体。
var builder = protobuf.newBuilder();
// 2.加载proto字符串:解析协议消息体定义。
var root = await protobuf.loadProto(protoStr, builder, "user.proto");
// 3.构建协议消息体。
var UserLoginResponse = root.build("com.user.UserLoginResponse");
// 设置编解码数据
const userLogin = {
sessionId: "loadProto",
userPrivilege: "John123",
isTokenType: false,
formatTimestamp: "12342222"
};
// 4.实例Message消息体:通过builder找到协议名后会产生Message,创建符合协议结构的数据对象,作为参数实例协议消息体。
var msg = new UserLoginResponse(userLogin);
// 5.消息体编码:可用于通信传递或存储
var arrayBuffer = msg.toArrayBuffer();
// 6.消息体解码:得到原始消息体内容
var decodeMsg = UserLoginResponse.decode(arrayBuffer);
} catch (error) {
console.info('protobuf single file catch error: ' + error)
}
});
2.json字符串编解码
Button("json字符串编解码")
.width('80%')
.type(ButtonType.Capsule)
.backgroundColor('#0D9FFB')
.onClick(async () => {
try {
// 1.创建protbuf.Builder对象:用于构造协议消息体。
var builder = protobuf.newBuilder();
// 2.加载json字符串:解析协议消息体定义。
var root = await protobuf.loadProto(protoJson, builder, "user.json");
// 3.构建协议消息体。
var UserLoginResponse = root.build("com.user.UserLoginResponse");
// 设置编解码数据
const userLogin = {
sessionId: "loadJson",
userPrivilege: "John123",
isTokenType: false,
formatTimestamp: "12342222"
};
// 4.实例Message消息体:通过builder找到协议名后会产生Message,创建符合协议结构的数据对象,作为参数实例协议消息体。
var msg = new UserLoginResponse(userLogin);
// 5.消息体编码:可用于通信传递或存储
var arrayBuffer = msg.toArrayBuffer();
// 6.消息体解码:得到原始消息体内容
var decodeMsg = UserLoginResponse.decode(arrayBuffer);
} catch (error) {
console.info('protobuf single file catch error: ' + error)
}
});
3.同步方式进行proto文件编解码
Button("同步方式进行proto文件编解码")
.width('80%')
.type(ButtonType.Capsule)
.backgroundColor('#0D9FFB')
.onClick(async () => {
try {
// 读取文件需要借助全球化资源子系统中的ResourceManager来进行,支持多种方式获取
// 方式一: 通过GlobalContext对象保存ability上下文中的resourceManager对象
// 方式二: 通过getContext()方式获取
// 在pages页面中获取: getContext(this).resourceManager
let context: Context = GlobalContext.getContext().getObject("context") as Context;
var builder = await protobuf.loadProtoFile('userproto.proto', null, null, context.resourceManager);
if (!builder) {
console.error('protobuf codec: builder is null|undefined.');
return;
}
var UserLoginResponse = builder.build("com.user.UserLoginResponse");
var msg = new UserLoginResponse(this.userLogin);
var arrayBuffer = msg.toArrayBuffer();
console.log("protobuf arrayBuffer:" + new Uint8Array(arrayBuffer));
var decodeMsg = UserLoginResponse.decode(arrayBuffer);
console.log("protobuf decode:" + JSON.stringify(decodeMsg));
} catch (error) {
console.info('protobuf single file catch error: ' + error)
}
});
4.异步方式进行proto文件编解码
Button("异步方式进行proto文件编解码")
.width('80%')
.type(ButtonType.Capsule)