如何仅使用一个 TypeMapper 将任何 protobuf Enum 生成为 String?
How to generate any protobuf Enum as String with only one TypeMapper?
例如,我的原型模式中有一些枚举:
enum E1 {
UNKNOWN = 0;
OPTION_1 = 1;
OPTION_2 = 2;
OPTION_3 = 3;
}
enum E2 {
UNKNOWN = 0;
ANOTHER_OPTION_1 = 1;
ANOTHER_OPTION_2 = 2;
ANOTHER_OPTION_3 = 3;
}
message M {
E1 my_enum_1 = 1;
E2 my_enum_2 = 2;
}
我可以通过提供 scalaPB
TypeMapper
s:
使用字符串而不是枚举生成 scala 类
TypeMapper(_.name)(E1.fromName(_).get)
TypeMapper(_.name)(E2.fromName(_).get)
但我不想为任何单个枚举复制粘贴相同的 TypeMappers
有什么方法可以为所有 scalaPB
的枚举只创建一个 TypeMapper?
您无法完全避免为每个 enum
类型定义 TypeMapper
。但是您可以创建一个辅助方法来创建 TypeMapper
个实例。
例如
import scalapb.GeneratedEnum
import scalapb.GeneratedEnumCompanion
import scalapb.TypeMapper
def enumMapper[E <: GeneratedEnum: GeneratedEnumCompanion] = {
TypeMapper[E, String](_.name)(implicitly[GeneratedEnumCompanion[E]].fromName(_).get)
}
---更新---
根据@thesamet 的评论,如果您将 implicit
添加到上述方法并在您的隐式上下文中使用它,它将起作用。
这可以用下面编译的代码进行测试
implicit def enumMapper...
val Enum1Mapper = implicitly[TypeMapper[E1]]
是的,这是可以做到的。
如果你想让 ScalaPB 对一个包中的所有枚举使用字符串,你可以添加 package-scoped options file to tell ScalaPB to set the scala-type for each enum to a String
using field transformations:
// options.proto:
syntax = "proto3";
import "scalapb/scalapb.proto";
option (scalapb.options) = {
scope: PACKAGE,
field_transformations : [
{
when : {
type: TYPE_ENUM
}
set : {[scalapb.field] {type : 'String'}}
}
}
下一步是为所有枚举定义类型映射器。借用 Ivan 的回答,这可以定义如下:
implicit def enumMapper[E <: GeneratedEnum](implicit ec: GeneratedEnumCompanion[E]) =
TypeMapper[E, String](_.name)(ec.fromName(_).get)
如果将上述代码添加到与生成代码相同的包中的包对象,或使用ScalaPB中的import
选项导入,类型映射器将在隐式搜索中找到。
例如,我的原型模式中有一些枚举:
enum E1 {
UNKNOWN = 0;
OPTION_1 = 1;
OPTION_2 = 2;
OPTION_3 = 3;
}
enum E2 {
UNKNOWN = 0;
ANOTHER_OPTION_1 = 1;
ANOTHER_OPTION_2 = 2;
ANOTHER_OPTION_3 = 3;
}
message M {
E1 my_enum_1 = 1;
E2 my_enum_2 = 2;
}
我可以通过提供 scalaPB
TypeMapper
s:
TypeMapper(_.name)(E1.fromName(_).get)
TypeMapper(_.name)(E2.fromName(_).get)
但我不想为任何单个枚举复制粘贴相同的 TypeMappers
有什么方法可以为所有 scalaPB
的枚举只创建一个 TypeMapper?
您无法完全避免为每个 enum
类型定义 TypeMapper
。但是您可以创建一个辅助方法来创建 TypeMapper
个实例。
例如
import scalapb.GeneratedEnum
import scalapb.GeneratedEnumCompanion
import scalapb.TypeMapper
def enumMapper[E <: GeneratedEnum: GeneratedEnumCompanion] = {
TypeMapper[E, String](_.name)(implicitly[GeneratedEnumCompanion[E]].fromName(_).get)
}
---更新---
根据@thesamet 的评论,如果您将 implicit
添加到上述方法并在您的隐式上下文中使用它,它将起作用。
这可以用下面编译的代码进行测试
implicit def enumMapper...
val Enum1Mapper = implicitly[TypeMapper[E1]]
是的,这是可以做到的。
如果你想让 ScalaPB 对一个包中的所有枚举使用字符串,你可以添加 package-scoped options file to tell ScalaPB to set the scala-type for each enum to a String
using field transformations:
// options.proto:
syntax = "proto3";
import "scalapb/scalapb.proto";
option (scalapb.options) = {
scope: PACKAGE,
field_transformations : [
{
when : {
type: TYPE_ENUM
}
set : {[scalapb.field] {type : 'String'}}
}
}
下一步是为所有枚举定义类型映射器。借用 Ivan 的回答,这可以定义如下:
implicit def enumMapper[E <: GeneratedEnum](implicit ec: GeneratedEnumCompanion[E]) =
TypeMapper[E, String](_.name)(ec.fromName(_).get)
如果将上述代码添加到与生成代码相同的包中的包对象,或使用ScalaPB中的import
选项导入,类型映射器将在隐式搜索中找到。