Custom Keys for Protobuf Maps

974 views
Skip to first unread message

AR

unread,
Oct 29, 2018, 6:29:37 PM10/29/18
to ScalaPB
One of the not-so-great things about proto3 is that maps have to have primitive types (string, int etc)

We can convert keys to custom types using the (scalapb.field).key_type field, but this requires a mapping from the business object to a simpler protobuf supported key. 

What is the practice for defining protobuf messages with typemappers such that the generated code exposes fields of type scala.immutable.Map[ComplexKey, ComplexValue] ?

The only way I see to do that is to have:

option (scalapb.options) = {
import: "my.namespace.TypeMappers._"
};

message KeyVal {
   Key key = 1;
   Val  val  = 2;
}

message KeyVals {
  repeated KeyVal key_vals = 1;
}

message MyMsg {
  KeyVals data = 1 [(scalapb.field).type = "scala.collection.immutable.Map[Key, Val]"]
}

Is there a way or a practice/pattern to define generic typemappers?
 
We end up creating 2 protobuf classes and one TypeMapper for every map this way. 

Nadav Samet

unread,
Oct 29, 2018, 7:31:45 PM10/29/18
to adity...@gmail.com, sca...@googlegroups.com
AFAIK, there's currently no way to have map with custom key types unless the custom key type maps to a key type that is allowed for proto3 maps. Looks like we can have a feature that allows the generated code to allow for all types by enabling some special option on repeated fields. Feel free to file a feature request with a proposal.

Best,
Nadav

--
You received this message because you are subscribed to the Google Groups "ScalaPB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalapb+u...@googlegroups.com.
To post to this group, send email to sca...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scalapb/90fdc456-62cd-4761-8498-10b7bedb7d23%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
-Nadav

Aditya Rao

unread,
Oct 29, 2018, 8:16:02 PM10/29/18
to Nadav Samet, sca...@googlegroups.com
Sounds interesting ...

So basically the Proto message would become

message MyMsg {
  repeated KeyVal myMap= 1; (scalapb.mapfield).keytype=Key, (scalapb.mapfield).valuetype=Value
}

And that automatically creates a Scala case class with a single field 

case class MyMsg(myMap: scala.immutable.Map[Key, Value] = Map.Empty)

?

Nadav Samet

unread,
Oct 29, 2018, 9:15:10 PM10/29/18
to adity...@gmail.com, sca...@googlegroups.com
As a user you'd have to define a message for KeyVal, because otherwise protoc won't be able to compile this. That makes scalapb.mapfield.keytype and valuetype unnecessary.

So I suggest something like:

message KeyValue {
   option (scalapb.message).map_entry = true;
   Key key = 1;
   Val  value  = 2;
}

message MyMsg {
  repeated KeyVal kv_map = 1; // generates kv_map: scala.collection.immutable.Map[Key, Val]
 
  // but the user can specify custom map types similar to custom collection types:
  repeated KeyVal kv_mutable_map = 2; [(scalapb.field).collection_type="collection.mutable.HashMap"]
}

--
-Nadav

Aditya Rao

unread,
Oct 29, 2018, 10:02:34 PM10/29/18
to thes...@gmail.com, sca...@googlegroups.com
This sounds great, how do I file a feature request, and what would be the rough eta?

Nadav Samet

unread,
Oct 29, 2018, 10:05:26 PM10/29/18
to adity...@gmail.com, sca...@googlegroups.com
You can file a feature request https://github.com/scalapb/ScalaPB/issues
ETA can be reduced if you are able to work on it :), otherwise I hope I can get to it at some point in the next few weeks.

-Nadav

--
-Nadav
Reply all
Reply to author
Forward
0 new messages