5

I'm using ScalaPB to compile my Scala case classes for serializing my protobuf messages.

I have a .proto file with the following messages:

message WrapperMessage {
    oneof msg {
        Login login = 1;
        Register register = 2;
    }
}

message Login {
    required string email = 1;
    required string password = 2;
}

message Register {
    required string email = 1;
    required string password = 2;
    optional string firstName = 3;
    optional string lastName = 4;
}

How do I create my WrapperMessage knowing that I want to put a Login message inside the msg?

  val login = Login(email = "test@example.com", password = "testpass")
  val wrapperMessage = WrapperMessage(???)
  val wrapperMessageBytes = wrapperMessage.toByteArray

Let's say now that I am receiving a WrapperMessage over the wire; how do I deserialize the message using ScalaPB case class methods?

Edward Maxedon
  • 1,151
  • 2
  • 11
  • 17

2 Answers2

6

ScalaPB has documentation which clearly provides examples for the questions I am asking. In this answer I tailor the examples provided on ScalaPB towards my question.

To initialize a message with oneof:

val login = Login(email = "test@example.com", password = "testpass")
val wrapperMessage = WrapperMessage().withLogin(login)

To match against a message's oneof field:

wrapperMessage.msg match {
  case Msg.Login(l) =>  // handle l
  case Msg.Register(r) =>  // handle r
  case Msg.Empty =>  // handle exceptional case...
}
Edward Maxedon
  • 1,151
  • 2
  • 11
  • 17
  • I've used ScalaPB before but not the `oneof` feature. It's good to see that they've translated the Java API to more idiomatic Scala patterns where possible. – kliew Mar 31 '16 at 04:09
1

You should be able to initialize WrapperMessage with an empty constructor and call .set_login(login)

You would deserialize to WrapperMessage and pattern match on message.WhichOneof which returns either "login" or "register". Then you would call the accessor on that specific message (ie. message.login).

kliew
  • 3,073
  • 1
  • 14
  • 25
  • I was able to initialize `WrapperMessage` succesfully using your advice. In Scala I used `WrapperMessage().setLogin(login)`. I believe `WhichOneof` is available only in the Python API. I can only use methods that are in the Java API using ScalaPB. Is there an elegant solution here? – Edward Maxedon Mar 30 '16 at 21:26
  • Oh, the Java API has `getOneofNameCase` which returns an enum to indicated which field is set. The enum should be defined in your protobuf scala definition, assuming that ScalaPB supports it. – kliew Mar 30 '16 at 21:30
  • I'm sure there is a solution that works like this, but found my answer simply looking towards ScalaPB's [documentation](https://trueaccord.github.io/ScalaPB/generated-code.html)... – Edward Maxedon Mar 30 '16 at 22:14