protobufjs
本项目基于 protobufjs 开发。
简介
protobufjs(protocol buffers) 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。,是一种灵活,高效,自动化机制的结构数据序列化方法比XML更小,更快,更为简单。
本项目主要是OpenHarmony系统下以protobufjs 7.2.4为主要依赖开发,主要接口针对OpenHarmony系统进行合理的适配研发。
下载安装
ohpm install @ohos/protobufjs
OpenHarmony ohpm环境配置等更多内容,请参考 如何安装OpenHarmony ohpm包 。
约束与限制
兼容性
在下述版本验证通过:
- DevEco Studio: 6.0.2 Release(6.0.2.642), SDK: API12 Release(5.0.0.71);
权限要求
无
使用示例
// user.js为protobufjs-cli生成的文件,已经按照使用说明替换相关文件,可参考demo提供的示例文件
import { user } from './user.js';
@Entry
@Component
struct Index {
build() {
Column() {
Button('编码并解码')
.onClick(() => {
// 创建消息对象
let message = user.UserLoginResponse.create({
sessionId: '215135415351435',
userPrivilege: 'John123',
isTokenType: false
});
// 执行编码
let bytes: Uint8Array = user.UserLoginResponse.encode(message).finish();
// 执行解码并输出结果
let decoded = user.UserLoginResponse.decode(bytes);
// 打印结果:`sessionId=215135415351435, userPrivilege=John123`
console.info(`protobufjs decode result: sessionId=${decoded.sessionId}, userPrivilege=${decoded.userPrivilege}`);
});
}
.width('100%')
.height('100%');
}
}
使用说明
1. 定义 proto 文件
在业务目录创建 proto 文件,按照.proto文件格式定义消息体结构,例如 user.proto:
syntax = "proto3";
package user;
message UserLoginResponse {
string sessionId = 1;
string userPrivilege = 2;
bool isTokenType = 3;
int64 formatTimestamp = 5;
bytes data = 6;
}
2. 生成 js 与 d.ts 文件
// 全局安装protobufjs
npm install -g protobufjs@7.2.4
// 全局安装protobufjs-cli
npm install -g protobufjs-cli
//在.proto文件目录下执行下列命令
pbjs -t static-module -w es6 -o user.js user.proto
pbts user.js -o user.d.ts
3. 修改生成文件中的导入
将生成的js文件中的 import * as $protobuf from "protobufjs/minimal";修改为:
// user.js
import $protobuf from '@ohos/protobufjs';
import Long from 'long';
$protobuf.util.Long = Long;
$protobuf.configure();
将生成的.d.ts文件中的 import * as $protobuf from "protobufjs";修改为:
// user.d.ts
import $protobuf from '@ohos/protobufjs';
4. 安装依赖并集成到工程
ohpm install long
将生成后的 user.js 与 user.d.ts 复制到应用工程,再按“使用示例”执行 create、encode、decode。
proto编码
import { user } from './user.js';
let msg = user.UserLoginResponse.create({
sessionId: "testSynchronouslyLoadProtoFile",
userPrivilege: "John123",
isTokenType: false,
formatTimestamp: 12342222
});
let bytes: Uint8Array = user.UserLoginResponse.encode(msg).finish();
proto解码
let decoded = user.UserLoginResponse.decode(bytes);
5. BigInt使用
// 在生成的js文件中 将$protobuf.util.Long 设置为undefined
import Long from 'long';
$protobuf.util.Long = undefined;
$protobuf.configure();
let msg = user.UserLoginResponse.create({
sessionId: "215135415351435",
userPrivilege: "John123",
isTokenType: false,
formatTimestamp: BigInt("9223372036854775807")
});
注意:本demo的user.d.ts代码文件,formatTimestamp属性支持的BigInt类型是当手动添加,并非通过任何命令生成。
6.protobufjs-cli使用说明
在文件格式之间转换并生成静态代码
-t, --target 指定目标格式,可以接受需要自定义目标的路径。
json JSON
json-module JSON表示为模块
proto2 Protocol Buffers, Version 2
proto3 Protocol Buffers, Version 3
static 无反射的静态代码(本身不起作用)
static-module 无反射模块的静态代码
-p, --path 将某个目录添加到包含路径中
-o, --out 保存文件而非写入到标准输出
--sparse 只导出从主文件引用的类型(实验)
仅限模块目标:
-w, --wrap 指定要使用的包装器,可接受需要自定义包装器的路径。
default 默认包装器支持CommonJS与AMD标准
commonjs CommonJS包装器
amd AMD包装器
es6 ES6包装器
closure 添加到全局protobuf的protobuf.roots上的闭包
--dependency 指定protobuf版本,可接受有效的模块ID。
-r, --root 指定备用的protobuf.roots名称
-l, --lint Linter配置,默认protbuf.js兼容规则:
eslint-disable block-scoped-var, id-length,
no-control-regex, no-magic-numbers, no-prototype-builtins,
no-redeclare, no-shadow, no-var, sort-vars
--es6 启用ES6语法
仅限原始源:
--keep-case 保留字段大小写而非是转换为驼峰大小写
仅限静态目标:
--no-create 不生成用于反射兼容性的创建函数.
--no-encode 不生成编码函数.
--no-decode 不生成解码函数.
--no-verify 不生成验证函数.
--no-convert 不生成转换函数
--no-delimited 不生成风格的编码/解码函数.
--no-beautify 不美化生成的代码.
--no-comments 不输出任何JSDoc注释.
--force-long 强制对s-/u-/int64和s-/fixed64字段使用Long
--force-number 强制对s-/u-/int64和s-/fixed64字段使用number
--force-message 强制使用消息而非普通对象
详细使用方式请参考:https://github.com/protobufjs/protobuf.js/blob/master/cli/README.md
7. 常见问题定位
- 若提示 Cannot find module 相关错误,先检查工程是否已安装 protobufjs 依赖链中的必需包。
- 若 int64 字段值异常,优先检查是否已设置 $protobuf.util.Long 并执行 $protobuf.configure()。
- 若使用分包或 HSP 场景,请确认导出模块路径和依赖包均可被目标模块解析。
接口说明
API
| 名称 | 类型 | 参数 | 返回值 | 必填 | OpenHarmony平台支持 | 描述 |
|---|---|---|---|---|---|---|
| create() | 方法 | properties?: Object | Object | 否 | 是 | 生成Message对象 |
| encode() | 方法 | message: Object, writer?: $protobuf.Writer | $protobuf.Writer | 是 | 是 | 编码消息 |
| decode() | 方法 | reader: $protobuf.Reader/Uint8Array, length?: number | Object | 是 | 是 | 解码消息 |
| verify() | 方法 | message: Object | string/null | 是 | 是 | 验证消息有效性 |
| fromObject() | 方法 | object: Object | Object | 是 | 是 | 从纯对象创建此类型的新消息。还将值转换为各自的内部类型 |
| toObject() | 方法 | message: Object, options?: $protobuf.IConversionOptions | Object | 是 | 是 | 将一个由键及其各自的值组成的数组转换为对象,省略未定义的值 |
关于混淆
- 代码混淆请参考 代码混淆简介。
- 若希望 protobufjs 在混淆后仍可正常调用,请在对应模块的 obfuscation-rules.txt 中添加排除规则:
-keep
./oh_modules/@ohos/protobufjs
常见问题
1. 提示缺少依赖模块
请确认已执行 ohpm install,并在工程中安装 long 与库自身依赖。
2. BigInt/int64 转换异常
请确认生成代码中已按文档设置 Long 或按业务要求将 util.Long 设为 undefined。
3. 生成代码导入失败
请确认 user.js、user.d.ts 中的 protobufjs 导入路径均已改为 @ohos/protobufjs。
目录结构
protobuf
├── AppScope/ # 应用级配置
├── entry/ # 示例工程
│ └── src/main/ets/pages/ # 示例页面与生成代码
├── library/ # 核心库模块
│ └── src/main/ets/ # protobufjs 主体代码与类型声明
├── README.md # 英文文档
├── README_zh.md # 中文文档
├── CHANGELOG.md # 版本变更记录
└── README.OpenSource # 开源声明
贡献代码
使用过程中发现问题可以提交 Issue,也欢迎提交 PR 共同完善。
开源协议
本项目基于 BSD 3-Clause License 开源。