0

I would like to make map in case class generated from protobuf wrapped in Option

case class Foo(aMap: Option[Map[String, String]])

For that I am trying to use scalapb.TypeMapper

package some.wrapper
import scalapb.TypeMapper
case class StringMapWrapper(map: Map[String, String])
object StringMapWrapper {
  implicit val mapper = TypeMapper(StringMapWrapper.apply)(_.map)
}

And the proto file looks like that:

syntax = "proto3";
package some;
import "scalapb/scalapb.proto";
message Foo {
  map<string, string> a_map = 1 [(scalapb.field).type = "some.wrapper.StringMapWrapper"];
}

But during compilation I have an error: --scala_out: some.Foo.a_map: Field a_map is a map and has type specified. Use key_type or value_type instead.

How can I fix this error?

Artem Petrov
  • 772
  • 4
  • 17

1 Answers1

1

The standard way in ScalaPB to get something inside an Option is to wrap it in a message:

syntax = "proto3";
package some;
import "scalapb/scalapb.proto";

message OptionalMap {
  option (scalapb.message).type = "Map[String, String]";
  map<string, string> inner = 1;
}

message UseCase {
  OptionalMap my_map = 1;
}

Due to the type option on OptionalMap, ScalaPB will generate myMap as an Option[Map[String, String]] instead of Option[OptionalMap]. Then only thing we need to do know is to provide a TypeMapper that will teach ScalaPB to convert between OptionalMap and Map[String, String]. To accomplish that, add the following to the package object UseCase is in:

package object some {
  implicit val OptionalMapMapper =
      scalapb.TypeMapper[some.myfile.OptionalMap, Map[String, String]](_.inner)(some.myfile.OptionalMap(_))
}
thesamet
  • 6,382
  • 2
  • 31
  • 42