Protobuf.js: how can i get the message define name from .proto?

Created on 2 Mar 2017  Â·  4Comments  Â·  Source: protobufjs/protobuf.js

protobuf.js version: <6.6.4>

i want to collect all the message names in a map, like below:

syntax = "proto3";

import "target.proto";
import "image.proto";
import ...

package protobuf;

message AcceptVoipRequest {
  Target target = 1; // 目标
}

// all my .proto files just like above

function getMessageName(proto) {
   let name
   // how to do this?
   // here name = 'AcceptVoipRequest'
   return name
}

protoNames.forEach(name => {
  let filePath = path.join(protoDir, name)
  let proto = ProtoBuf.loadSync(filePath)
  map[getMessageName(proto)] = proto
})

question

All 4 comments

Ideally, you'd just traverse through the root instance by calling a function with your logic for each message type within:

function traverseTypes(current, fn) {
  if (current instanceof protobuf.Type)
    fn(current);
  if (current.nestedArray)
    current.nestedArray.forEach(function(nested) {
      traverseTypes(nested, fn);
    });
}

Example:

var root = protobuf.loadSync(...);

traverseTypes(root, function(type) {
  console.log(type.fullName);
});

See also: API of protobuf.Type

Also created an example.

@dcodeIO that's not what i really want, your code above will display all the message names that a .proto file have(or imports). but i only want display the single name without any imports(for example i only want display the name: 'AcceptVoipRequest').

A Root instance always contains all types of messages loaded into it. To find a specific message within a specific file, you'd either have to examine that exact file, i.e. using a regular expression

var source = ...;
var re = /\bmessage\s+(\w+) /g;
var match;
while (match = re.exec(source)) {
   console.log(match[1]);
}

or to annotate the messages you'd like to expose in some way understood by reflection, so you can filter.

message AcceptVoipRequest {
  option someOption = true;
  Target target = 1; // 目标
}
traverseTypes(root, function(type) {
  if (type.options && type.options.someOption)
    console.log(type.fullName);
});

Additionally, reflection objects (messages, enums, services etc.) also have a filename property that you could use.

traverseTypes(root, function(type) {
  if (/\bAcceptVoipRequest\.proto$/.test(type.filename))
    console.log(type.fullName);
});

Likewise, all loaded files are present within Root#files (a string array).

See also: Updated example

@dcodeIO thanks a lot for your patience and help. Examine the exact file or the filename is fit for me. I finally solved this problem by examine the filename and fllow some rules of convention。

Was this page helpful?
0 / 5 - 0 ratings