找回密码
 立即注册
查看: 319|回复: 0

protobufjs 使用方法

[复制链接]
发表于 2022-3-5 10:11 | 显示全部楼层 |阅读模式

image

protobuf.js是一个纯JavaScript实现,支持Node.js和浏览器的TypeScript,它容易使用速度快速,可以直接反射.proto文件,不需要生成任何文件。

protobuf.js是基于ByteBuffer.js的Protocol Buffers纯JavaScript实现,主要功能是解析.proto文件,构建Message类,编码解码。
安装


下载安装protobufjs

https://github.com/protobufjs/protobuf.js

查看protobufjs候选版本
$ npm view protobufjs versions
使用NPM全局安装protobufjs
$ npm i -g protobufjs
protobuf.js 依赖 long.js、bytebuffer.js

创建.proto文件
$ vim msg.protosyntax = "proto3";package ns;message Login {    string name = 1;    string pwd = 2;}message Address{  required string province = 1;  required string city = 2;  required string country = 3;}转换


在命令行模式下,pbjs命令用于在文件格式之间转换,并可以生成静态代码。
$ pbjsprotobuf.js v6.7.0 CLI for JavaScript在文件格式之间转换并生成静态代码  -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  强制使用消息而非普通对象usage: pbjs [options] file1.proto file2.json ...  (or pipe)  other | pbjs [options] -
文件转换

使用pbjs命令将.proto文件转换为.json文件
$ ./node_modules/protobufjs/bin/pbjs -t json msg.proto > msg.json
使用pbjs命令将.proto文件转换为.js文件
$ ./node_modules/protobufjs/bin/pbjs -t static_module -w commonjs -o msg.js msg.proto
编写pbjs命令的转换脚本
$ vim pbjs.cmd::判断当前目录是否存在node.exe@IF EXIST "%~dp0\node.exe" (    ::使用node执行pbjs进行文件转换    "%~dp0\node.exe" "%~dp0\..\protobufjs\bin\pbjs" %*) ELSE (    @SETLOCAL    ::将环境变量PATHEXT中的JS删除    @SET PATHEXT=%PATHEXT:;.JS;=;%    ::使用node执行pbjs进行文件转换    node "%~dp0\.. \protobufjs\bin\pbjs" %*)使用


由于JavaScript是一种动态类型语言, protobuf.js引入有效消息的概念,以便提供最佳的性能。

image

不同方法与有效消息之间的关系
方法描述
Message.verify(message:Object):nullstring验证普通JavaScript对象是否满足有效消息的要求,以确保无错误的进行加密编码(encode)。verify不抛出错误而会将错误消息作为字符串返回。
Message.encode(message:MessageObject [, writer:Writer]):Writer对消息实例或有效的纯JavaScript对象进行编码,encode不隐式的验证消息,而由用户确定有效负载是有效消息。
Message.encodeDelimited(message:MessageObjecct [, writer:Writer]):Writer将protobuffer解码为消息实例,如果required字段缺少则会抛出util.ProtocolError错误。
Message.decodeDelimited(reader:ReaderUint8Array):Message工作方式类似于decode函数,会另外读取一个消息的长度作为变量的预设值。
Message.create(properties:Object):Message从一组满足有效消息要求的属性中创建一个新消息实例,如果适用,建议首选create而非fromObject,因为create不会执行可能存在冗余的转换。
Message.fromObject(object:Object):Message将任何无效的纯JavaScript对象转换为消息实例
Message.toObject(message:Message [, options:ConversionOptions]):Object将消息实例转换为任意纯JavaScript对象,以便与其它库或存储进行互操作。根据指定的实际转换选项,生成纯JavaScript对象。
初始化

$ npm i -g requirelet pbroot = require("protobufjs").Root;let json = require("msg.json");let root = pbroot.fromJSON(json);let Message = root.lookupType("ns.Address");创建

Message.create(properties:Object):Message
从一组满足有效消息要求的属性中创建一个新消息实例,如果适用,建议首选create而非fromObject,因为create不会执行可能存在冗余的转换。

例如;
//数据let data = {province:"", city:"", area:""};data.province = "hunan";data.city = "changsha";data.area = "yuelu";//创建let message = Message.create(data);console.log(message);//Address {province: "hunan", city: "changsha", area: "yuelu"}验证

Message.verify(message:Object):null|string
验证普通JavaScript对象是否满足有效消息的要求,以确保无错误的进行加密编码(encode)。

verify不抛出错误而会将错误消息作为字符串返回。
let message = Message.create({province:"hunan"});let errmsg = Message.verify(message);if(errmsg){  throw Error(errmsg);}序列化编码

Message.encode(message: Message|Object [, writer: Writer]): Writer
对消息实例或有效的纯JavaScript对象进行编码,encode不隐式的验证消息,而由用户确定有效负载是有效消息。
let data = {};data.province= "hunan";data.city = "changsha";let buffer= Message.encode(Message.create(data)).finish();反序列化解码

Message.decode(reader: Reader|Uint8Array): Message
将protobuffer解码为消息实例,如果缺乏required字段则抛出util.ProtocolError错误,如果wire格式无效也会抛出错误。
//解码try{    let message = Message.decode(buffer);}catch(e){    if(e instanceof protobuf.util.ProtocolError){        //missing required field    }else{        //wire format is invalid    }}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-5-10 01:17 , Processed in 0.133484 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表