You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否有库可将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:24:53