protobufjs

protobufjs

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.proto
syntax = "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命令用于在文件格式之间转换,并可以生成静态代码。

$ pbjs
protobuf.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引入有效消息的概念,以便提供最佳的性能。

有效消息

不同方法与有效消息之间的关系

方法 描述
Message.verify(message:Object):null|string 验证普通JavaScript对象是否满足有效消息的要求,以确保无错误的进行加密编码(encode)。verify不抛出错误而会将错误消息作为字符串返回。
Message.encode(message:Message|Object [, writer:Writer]):Writer 对消息实例或有效的纯JavaScript对象进行编码,encode不隐式的验证消息,而由用户确定有效负载是有效消息。
Message.encodeDelimited(message:Message|Objecct [, writer:Writer]):Writer 将protobuffer解码为消息实例,如果required字段缺少则会抛出util.ProtocolError错误。
Message.decodeDelimited(reader:Reader|Uint8Array):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 require
let 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
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容