美文网首页
protobufjs 使用方法

protobufjs 使用方法

作者: yichen_china | 来源:发表于2022-03-05 08:28 被阅读0次
    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.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;
    }
    
    

    这个是使用cim框架时候实际使用中有map类

    syntax = "proto3";
    package com.farsunset.cim.sdk.server.model.proto;
    option java_outer_classname="ReplyBodyProto";
    
    message Model {
       string key = 1;
       string code = 2;
       string message = 3;
       int64 timestamp =4;
       map<string,string> data =5;
       
    }
         
    

    转换

    在命令行模式下,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
    
    

    得到的msg.js文件是json格式
    在前面加上module.exports =
    例如:

    module.exports ={
    js文件的全部内容
      "nested": {
        "com": {
          "nested": {
            "farsunset": {
              "nested": {
                "cim": {
                  "nested": 
    ……………………省略
    }
    

    使用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):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
        }
    }
    

    相关文章

      网友评论

          本文标题:protobufjs 使用方法

          本文链接:https://www.haomeiwen.com/subject/ozmvrrtx.html