0

将 grpc 与 Node 一起使用,响应我的查询的枚举解析为整数值。但是,当我使用 BloomRPC 进行相同的查询时,枚举解析为整数值。

是否有参数或选项可以强制使用 Node grpc 将这些枚举解析为字符串?

4

2 回答 2

1

如果您正在使用该@grpc/proto-loader库,则可以将选项设置enums为值String(不是字符串“String”,构造函数String)。然后所有枚举值都将由它们的名称字符串表示。

于 2019-10-23T17:09:12.637 回答
1

在我们的项目中,我们enum通过消除人为错误来帮助我们确保有限的可能性集的完整性。enum当我们有这么方便的协议缓冲区时,为什么我们需要记住字符串值是什么?因此,我们使用.proto作为真理的来源;这是我们的规则。

为此,请按照为 ES6+ 代码编写的这些步骤进行操作。

  1. gRPC/Protobuf enum.proto文件中定义你的。
// life.proto
syntax = 'proto3';
package life;

enum Choices
{
  EAT = 0;
  DRINK = 1;
  SLEEP = 2;
  CODE = 3;
  SKI = 4;
}
  1. 安装@grpc/proto-loader@grpc/grpc-js.
$ npm i -s @grpc/proto-loader @grpc/grpc-js
  1. 可以说,导入支付账单的模块。将文件直接加载.proto到内存中(不要编译)。
// myNodeApp.js
import * as grpc from '@grpc/grpc-js'
import * as protoLoader from '@grpc/proto-loader'
import path from 'path'

// these options help make definitions usable in our code
const protoOptions = {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true
}

// this allows us to prepare the path to the current dir
const dir = path.dirname(new URL(import.meta.url).pathname)
// this loads the .proto file
const lifeDef = protoLoader.loadSync(path.join(dir, 'life.proto'), protoOptions)
// this loads the package 'life' from the .proto file
const life = grpc.loadPackageDefinition(lifeDef).life
  1. 查看enum Choices定义(在同一个文件中)。
// myNodeApp.js (cont'd)
console.log(life.Choices)

/* stdout */
{
  format: 'Protocol Buffer 3 EnumDescriptorProto',
  type: {
    value: [ [Object], [Object], [Object], [Object], [Object] ],
    name: 'Choices',
    options: null
  },
  fileDescriptorProtos: [
    <Buffer 0a ... 328 more bytes>
  ]
}

……看深一点……

console.log(life.Choices.value)

/* stdout */
{
  value: [
    { name: 'EAT', number: 0, options: null },
    { name: 'DRINK', number: 1, options: null },
    { name: 'SLEEP', number: 2, options: null },
    { name: 'CODE', number: 3, options: null },
    { name: 'SKI', number: 4, options: null }
  ],
  name: 'Choices',
  options: null
}

  1. 使用enum.
// myNodeApp.js
const myDay = { // plain JSON (or define a gRPC message, same same)
  dawn: life.Choices.type.value[1].name,
  morning: life.Choices.type.value[0].name,
  afternoon: life.Choices.type.value[4].name,
  evening: life.Choices.type.value[3].name,
  night: life.Choices.type.value[2].name
}

您可以编写访问器或实用程序函数来管理键查找(通过传递导入的grpc enum和索引),如下所示:

export const getEnumByName = function (protoEnum, needle) {
  return protoEnum.type.value.find(p => {
    return p.name === needle
  })
}

export const getEnumByNum = function (protoEnum, needle) {
  return protoEnum.type.value.filter(p => {
    return p.number = needle
  })
}

export const getEnumKeys = function (protoEnum, key = 'name') {
  return protoEnum.type.value.map(p => {
    return p[key]
  })
}

反转并将值分配给 aMessage是其他答案中已经涵盖的内容,只需将枚举字段设置为字符串值,您猜对了,使用表示枚举名称的字符串,您可以使用上面的代码访问该字符串。

这与我们的做法一致。干净简单,只是有点晦涩,直到有一天你看起来“在引擎盖下”。

了解更多关于@grpc/proto-loader@grpc/grpc-js 的信息。希望这可以帮助野外的人。:)

于 2021-03-08T07:24:32.960 回答