参考链接:https://github.com/protobufjs/protobuf.js#installation
简介
Protocol Buffers是一种跨语言、跨平台、可扩展的序列化结构化数据的方式,用于通信协议、数据存储等,最初由Google设计。
protobuf.js是一个纯JavaScript实现,支持node.js和浏览器的TypeScript。它易于使用,速度惊人,并且可以与.proto文件一起开箱即用!
安装
npm install protobufjs
或者
开发环境:
<script src=“//cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.js“></script>
生产环境:
<script src=“//cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js“></script>
用项目所依赖的确切版本替换版本标记。
文件转换
.proto文件
option java_package = "test";
option java_outer_classname = "TestProtocol";
message Address{
required string province = 1;
required string city = 2;
optional string country = 3;
}
安装pbjs
npm -g install protobufjs-cli
使用pbjs命令将.proto文件转换为.json文件
pbjs -t json src/lib/proto/chat.proto > src/lib/proto/chat.proto.json
生成js静态模块文件
pbjs -t static-module -w commonjs -o src/lib/proto/chat.js src/lib/proto/chat.proto
生成ts声明文件
pbts -o src/lib/proto/chat.d.ts src/lib/proto/chat.js
该库支持三种模式
- protobufjs
https://cdn.jsdelivr.net/npm/protobufjs/dist/
完整版:protobufjs 是 Protobuf.js 库的完整版,提供了广泛的功能和特性,包括加载和解析 Protocol Buffers 定义文件、生成消息对象、编码和解码消息、支持扩展、服务定义等。
包大小:由于包含了完整的功能集合,protobufjs 的包大小相对较大。
2.protobufjs/minimal
https://cdn.jsdelivr.net/npm/protobufjs/dist/minimal/
精简版:protobufjs/minimal 是 Protobuf.js 库的精简版,专注于提供最小的功能集合。
功能限制:相对于完整版的 protobufjs,protobufjs/minimal 版本可能缺少一些高级特性和扩展功能。
包大小:由于只包含最基本的功能,protobufjs/minimal 的包大小相对较小。这使得它在资源受限的环境下更适用。
3.protobufjs/light
https://cdn.jsdelivr.net/npm/protobufjs/dist/light/
轻量级版:protobufjs/light 是 Protobuf.js 库的轻量级版,旨在提供最小的功能集合和最小的包大小。
功能限制:相对于完整版的 protobufjs,protobufjs/light 版本进一步削减了功能和特性,通常只提供了最基本的加载和解析功能。
包大小:protobufjs/light 的包大小最小,它被优化为适用于资源受限的环境,如浏览器端
https://blog.youkuaiyun.com/m0_74278725/article/details/129048283?spm=1001.2014.3001.5502
代码示例解析
1、$protobuf.Reader
是 Protobuf.js 库中的一个类,用于解析从二进制数据中读取 Protocol Buffers 消息。
作为 Protobuf.js 库的一部分,protobuf.Reader 提供了一系列方法,用于从二进制数据中读取不同类型的字段值。它的主要作用是解析二进制数据,并将其转换为消息对象中定义的字段值。
以下是 protobuf.Reader 类的一些常用方法和功能:
uint32()、int32()、sint32() 等方法:用于从二进制数据中读取不同类型的整数字段。
float()、double():用于读取浮点数字段。
bool():用于读取布尔值字段。
string()、bytes():用于读取字符串和字节数组字段。
skip():用于跳过指定长度的数据。
fork()、reset():用于在解析过程中创建快照和重置解析位置。
通过使用 protobuf.Reader,你可以按照消息定义的结构,逐个读取二进制数据中的字段,并将其解析为相应的数据类型。这使得你可以在 JavaScript 中方便地处理和操作 Protocol Buffers 数据。
2、$protobuf.Writer
是 Protobuf.js 库中的一个类,用于将 JavaScript 对象中的数据编码为二进制格式的 Protocol Buffers 消息。
作为 Protobuf.js 库的一部分,$protobuf.Writer 提供了一系列方法,用于将不同类型的字段值写入到二进制数据中。它的主要作用是将消息对象中定义的字段值转换为二进制格式,以便进行传输或持久化存储。
以下是 $protobuf.Writer 类的一些常用方法和功能:
uint32()、int32()、sint32() 等方法:用于写入不同类型的整数字段。
float()、double():用于写入浮点数字段。
bool():用于写入布尔值字段。
string()、bytes():用于写入字符串和字节数组字段。
fork()、reset():用于在编码过程中创建快照和重置编码位置。
通过使用 $protobuf.Writer,你可以将 JavaScript 对象中的字段值按照消息定义的结构写入到二进制数据中,以便进行传输或持久化存储。这使得你可以在 JavaScript 中方便地处理和操作 Protocol Buffers 数据。
3、$protobuf.util
是 Protobuf.js 库中的一个模块,提供了一些实用功能和工具函数,用于处理 Protocol Buffers 相关的操作。
在 $protobuf.util 模块中,你可以找到以下一些常用的功能和函数:
base64: 提供了 base64 编码和解码的功能。
utf8: 提供了 UTF-8 编码和解码的功能。
merge: 用于合并多个对象。
emptyArray: 表示空数组的常量。
emptyObject: 表示空对象的常量。
decorateType: 用于装饰类型,添加一些额外的属性和方法。
isInteger: 判断一个值是否为整数。
isString: 判断一个值是否为字符串。
stringToLong: 将字符串转换为 Long 类型。
longToString: 将 Long 类型转换为字符串。
以上仅列举了一些 $protobuf.util 模块中的常用功能和函数,实际上还有更多的工具函数可供使用。你可以参考 Protobuf.js 的官方文档中的 $protobuf.util 部分,了解更详细的功能和用法。
p r o t o b u f . r o o t s [ " d e f a u l t " ] ∣ ∣ ( protobuf.roots["default"] || ( protobuf.roots["default"]∣∣(protobuf.roots[“default”] = {})
是 Protobuf.js 库中的一行代码,用于获取或创建名为 “default” 的根命名空间。
在 Protobuf.js 中,根命名空间是用于存储已加载的 Protocol Buffers 定义文件和消息类型的对象。通过根命名空间,你可以访问和操作加载的定义文件和消息类型,进行编码、解码、验证等操作。
具体示例
var $protobuf = require("protobufjs/minimal");
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.ExamUser = (function() {
/**
* Properties of an ExamUser.
* @exports IExamUser
* @interface IExamUser
* @property {string} userId ExamUser userId
* @property {string|null} [avatar] ExamUser avatar
* @property {ExamUser.RoleType} roleType ExamUser roleType
* @property {string|null} [userName] ExamUser userName
*/
/**
* Constructs a new ExamUser.
* @exports ExamUser
* @classdesc Represents an ExamUser.
* @implements IExamUser
* @constructor
* @param {IExamUser=} [properties] Properties to set
*/
function ExamUser(properties) {
if (properties)
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null)
this[keys[i]] = properties[keys[i]];
}
/**
* ExamUser userId.
* @member {string} userId
* @memberof ExamUser
* @instance
*/
ExamUser.prototype.userId = "";
// ...
/**
* ExamUser userName.
* @member {string} userName
* @memberof ExamUser
* @instance
*/
ExamUser.prototype.userName = "";
/**
* Creates a new ExamUser instance using the specified properties.
* @function create
* @memberof ExamUser
* @static
* @param {IExamUser=} [properties] Properties to set
* @returns {ExamUser} ExamUser instance
*/
ExamUser.create = function create(properties) {
return new ExamUser(properties);
};
/**
* Encodes the specified ExamUser message. Does not implicitly {@link ExamUser.verify|verify} messages.
* @function encode
* @memberof ExamUser
* @static
* @param {IExamUser} message ExamUser message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
ExamUser.encode = function encode(message, writer) {
if (!writer)
writer = $Writer.create();
writer.uint32(/* id 1, wireType 2 =*/10).string(message.userId);
// ....
return writer;
};
/**
* Encodes the specified ExamUser message, length delimited. Does not implicitly {@link ExamUser.verify|verify} messages.
* @function encodeDelimited
* @memberof ExamUser
* @static
* @param {IExamUser} message ExamUser message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
ExamUser.encodeDelimited = function encodeDelimited(message, writer) {
return this.encode(message, writer).ldelim();
};
/**
* Decodes an ExamUser message from the specified reader or buffer.
* @function decode
* @memberof ExamUser
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Message length if known beforehand
* @returns {ExamUser} ExamUser
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
ExamUser.decode = function decode(reader, length) {
if (!(reader instanceof $Reader))
reader = $Reader.create(reader);
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.ExamUser();
while (reader.pos < end) {
var tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
message.userId = reader.string();
break;
}
case 2: {
message.avatar = reader.string();
break;
}
case 3: {
message.roleType = reader.int32();
break;
}
case 4: {
message.userName = reader.string();
break;
}
default:
reader.skipType(tag & 7);
break;
}
}
if (!message.hasOwnProperty("userId"))
throw $util.ProtocolError("missing required 'userId'", { instance: message });
if (!message.hasOwnProperty("roleType"))
throw $util.ProtocolError("missing required 'roleType'", { instance: message });
return message;
};
/**
* Decodes an ExamUser message from the specified reader or buffer, length delimited.
* @function decodeDelimited
* @memberof ExamUser
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {ExamUser} ExamUser
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
ExamUser.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof $Reader))
reader = new $Reader(reader);
return this.decode(reader, reader.uint32());
};
/**
* Verifies an ExamUser message.
* @function verify
* @memberof ExamUser
* @static
* @param {Object.<string,*>} message Plain object to verify
* @returns {string|null} `null` if valid, otherwise the reason why it is not
*/
ExamUser.verify = function verify(message) {
if (typeof message !== "object" || message === null)
return "object expected";
if (!$util.isString(message.userId))
return "userId: string expected";
if (message.avatar != null && message.hasOwnProperty("avatar"))
if (!$util.isString(message.avatar))
return "avatar: string expected";
switch (message.roleType) {
default:
return "roleType: enum value expected";
case 1:
case 2:
case 0:
case 3:
break;
}
if (message.userName != null && message.hasOwnProperty("userName"))
if (!$util.isString(message.userName))
return "userName: string expected";
return null;
};
/**
* Creates an ExamUser message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof ExamUser
* @static
* @param {Object.<string,*>} object Plain object
* @returns {ExamUser} ExamUser
*/
ExamUser.fromObject = function fromObject(object) {
if (object instanceof $root.ExamUser)
return object;
var message = new $root.ExamUser();
if (object.userId != null)
message.userId = String(object.userId);
if (object.avatar != null)
message.avatar = String(object.avatar);
switch (object.roleType) {
default:
if (typeof object.roleType === "number") {
message.roleType = object.roleType;
break;
}
break;
case "EXAMINEE":
case 1:
message.roleType = 1;
break;
// ....
}
if (object.userName != null)
message.userName = String(object.userName);
return message;
};
/**
* Creates a plain object from an ExamUser message. Also converts values to other types if specified.
* @function toObject
* @memberof ExamUser
* @static
* @param {ExamUser} message ExamUser
* @param {$protobuf.IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
*/
ExamUser.toObject = function toObject(message, options) {
if (!options)
options = {};
var object = {};
if (options.defaults) {
object.userId = "";
object.avatar = "";
object.roleType = options.enums === String ? "EXAMINEE" : 1;
object.userName = "";
}
if (message.userId != null && message.hasOwnProperty("userId"))
object.userId = message.userId;
// ....
return object;
};
/**
* Converts this ExamUser to JSON.
* @function toJSON
* @memberof ExamUser
* @instance
* @returns {Object.<string,*>} JSON object
*/
ExamUser.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
/**
* Gets the default type url for ExamUser
* @function getTypeUrl
* @memberof ExamUser
* @static
* @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns {string} The default type url
*/
ExamUser.getTypeUrl = function getTypeUrl(typeUrlPrefix) {
if (typeUrlPrefix === undefined) {
typeUrlPrefix = "type.googleapis.com";
}
return typeUrlPrefix + "/ExamUser";
};
/**
* RoleType enum.
* @name ExamUser.RoleType
* @enum {number}
* @property {number} EXAMINEE=1 EXAMINEE value
* @property {number} EXAMINER=2 EXAMINER value
* @property {number} SYSTEM=0 SYSTEM value
* @property {number} CORP_ADMIN_USER=3 CORP_ADMIN_USER value
*/
ExamUser.RoleType = (function() {
var valuesById = {}, values = Object.create(valuesById);
values[valuesById[1] = "EXAMINEE"] = 1;
return values;
})();
return ExamUser;
})();
module.exports = $root;