如何使用 Node grpc 将枚举解析为字符串值?
How to resolve Enums as String values with Node grpc?
将 grpc 与 Node 结合使用,响应我的查询的枚举解析为整数值。但是,当我使用 BloomRPC 进行相同的查询时,枚举解析为整数值。
是否有参数或选项强制使用 Node grpc 将这些枚举解析为字符串?
如果您使用的是 @grpc/proto-loader
library, you can set the option enums
to the value String
(not the string "String", the constructor function String
)。然后所有枚举值将由它们的名称字符串表示。
在我们的项目中,我们使用 enum
来帮助我们通过消除人为错误来确保有限可能性集的完整性。当我们有协议缓冲区 enum
如此方便时,为什么我们需要记住字符串值是什么?因此,我们使用 .proto
作为事实来源;这是我们的规则。
为此,请按照为 ES6+ 代码编写的这些步骤操作。
- 在
.proto
文件中定义您的 gRPC/Protobuf enum
。
// life.proto
syntax = 'proto3';
package life;
enum Choices
{
EAT = 0;
DRINK = 1;
SLEEP = 2;
CODE = 3;
SKI = 4;
}
- 安装
@grpc/proto-loader
和@grpc/grpc-js
。
$ npm i -s @grpc/proto-loader @grpc/grpc-js
- 可以这么说,导入支付账单的模块。将
.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
- 查看
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
}
- 使用
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]
})
}
反转并为 Message
赋值是其他答案中已经涵盖的内容,只需将枚举字段设置为字符串值,您猜对了,代表枚举名称,您可以使用上面的代码访问它。
这与我们的做法一致。简洁明了,只有一点点晦涩难懂,直到有一天你看到“引擎盖下”。
了解有关 @grpc/proto-loader and @grpc/grpc-js 的更多信息。希望这可以帮助野外的人。 :)
将 grpc 与 Node 结合使用,响应我的查询的枚举解析为整数值。但是,当我使用 BloomRPC 进行相同的查询时,枚举解析为整数值。
是否有参数或选项强制使用 Node grpc 将这些枚举解析为字符串?
如果您使用的是 @grpc/proto-loader
library, you can set the option enums
to the value String
(not the string "String", the constructor function String
)。然后所有枚举值将由它们的名称字符串表示。
在我们的项目中,我们使用 enum
来帮助我们通过消除人为错误来确保有限可能性集的完整性。当我们有协议缓冲区 enum
如此方便时,为什么我们需要记住字符串值是什么?因此,我们使用 .proto
作为事实来源;这是我们的规则。
为此,请按照为 ES6+ 代码编写的这些步骤操作。
- 在
.proto
文件中定义您的gRPC/Protobuf enum
。
// life.proto
syntax = 'proto3';
package life;
enum Choices
{
EAT = 0;
DRINK = 1;
SLEEP = 2;
CODE = 3;
SKI = 4;
}
- 安装
@grpc/proto-loader
和@grpc/grpc-js
。
$ npm i -s @grpc/proto-loader @grpc/grpc-js
- 可以这么说,导入支付账单的模块。将
.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
- 查看
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
}
- 使用
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]
})
}
反转并为 Message
赋值是其他答案中已经涵盖的内容,只需将枚举字段设置为字符串值,您猜对了,代表枚举名称,您可以使用上面的代码访问它。
这与我们的做法一致。简洁明了,只有一点点晦涩难懂,直到有一天你看到“引擎盖下”。
了解有关 @grpc/proto-loader and @grpc/grpc-js 的更多信息。希望这可以帮助野外的人。 :)