是否有库可将Protocol Buffer生成的Scala类映射为简易case class?
问题:将Scalapb生成的Protobuf类映射为简易Case Class
是否存在相关库,能够将Protocol Buffer编译器(如Scalapb)从.proto文件生成的Scala类,映射为不含额外字段与方法的简易Scala case class?当前生成的文件未提供映射函数,是否必须手动完成映射?
示例代码
生成的Scalapb类:
final case class PartnerConversionRates( conversionRate: _root_.scala.Option[_root_.scala.Double] = _root_.scala.None, redemptionFactor: _root_.scala.Option[_root_.scala.Double] = _root_.scala.None, unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[PartnerConversionRates] { @transient private[this] var __serializedSizeCachedValue: _root_.scala.Int = 0 private[this] def __computeSerializedValue(): _root_.scala.Int = { var __size = 0 if (conversionRate.isDefined) { val __value = com.myCompany.my_team.myClass.proto.PartnerConversionRates._typemapper_conversionRate.toBase(conversionRate.get) __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize }; if (redemptionFactor.isDefined) { val __value = com.myCompany.my_team.myClass.proto.PartnerConversionRates._typemapper_redemptionFactor.toBase(redemptionFactor.get) __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize }; __size += unknownFields.serializedSize __size } // 省略其余方法 }
目标简易Case Class:
case class PartnerConversionRates( /* Conversion Rate of partner */ conversionRate: Option[Double] = None, /* Redemption Rate of partner */ redemptionFactor: Option[Double] = None )
解决方案
不需要手动完成所有映射,有几种更高效的方案可选:
自定义Scalapb生成模板
Scalapb支持通过自定义插件或修改生成模板,直接生成两类代码:一类是用于Protobuf序列化的原始GeneratedMessage类,另一类是你需要的简易case class。只需在模板中过滤掉unknownFields字段,去掉多余的特质继承和序列化相关方法,就能一次性得到目标类,同时保留原始类的序列化能力。使用类型推导类库自动映射
借助Magnolia或Shapeless这类基于Scala类型系统的库,能自动推导生成类与简易类之间的映射逻辑。因为两类的核心字段名、类型完全匹配(仅全限定名差异不影响),这些库可以生成通用的转换函数,无需手动编写每个字段的映射代码,还能自动忽略unknownFields这类额外字段。编译期代码生成
用Scala宏或sbt代码生成插件(如sbt-codegen),在编译阶段扫描Scalapb生成的类,自动提取需要的字段并生成简易case class及对应的转换方法。这种方式能批量处理多个Protobuf类,避免重复劳动。
如果项目依赖限制较多,手动编写映射方法也不失为简单直接的选择——因为字段对应关系明确,写个转换函数只需要几行代码:
def toSimple(pb: PartnerConversionRates): PartnerConversionRates = { PartnerConversionRates( conversionRate = pb.conversionRate, redemptionFactor = pb.redemptionFactor ) }
内容的提问来源于stack exchange,提问作者Freez
相关产品推荐
相关产品推荐

