scala-protobuf-java-macro


License

License

Categories

Categories

Java Languages Scala Protobuf Data Data Structures
GroupId

GroupId

com.github.changvvb
ArtifactId

ArtifactId

scala-protobuf-java-macro_2.12
Last Version

Last Version

0.2.0
Release Date

Release Date

Type

Type

jar
Description

Description

scala-protobuf-java-macro
scala-protobuf-java-macro
Project URL

Project URL

https://github.com/changvvb/scala-protobuf-java
Project Organization

Project Organization

com.github.changvvb
Source Code Management

Source Code Management

https://github.com/changvvb/scala-protobuf-java

Download scala-protobuf-java-macro_2.12

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.changvvb/scala-protobuf-java-macro_2.12/ -->
<dependency>
    <groupId>com.github.changvvb</groupId>
    <artifactId>scala-protobuf-java-macro_2.12</artifactId>
    <version>0.2.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.changvvb/scala-protobuf-java-macro_2.12/
implementation 'com.github.changvvb:scala-protobuf-java-macro_2.12:0.2.0'
// https://jarcasting.com/artifacts/com.github.changvvb/scala-protobuf-java-macro_2.12/
implementation ("com.github.changvvb:scala-protobuf-java-macro_2.12:0.2.0")
'com.github.changvvb:scala-protobuf-java-macro_2.12:jar:0.2.0'
<dependency org="com.github.changvvb" name="scala-protobuf-java-macro_2.12" rev="0.2.0">
  <artifact name="scala-protobuf-java-macro_2.12" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.changvvb', module='scala-protobuf-java-macro_2.12', version='0.2.0')
)
libraryDependencies += "com.github.changvvb" % "scala-protobuf-java-macro_2.12" % "0.2.0"
[com.github.changvvb/scala-protobuf-java-macro_2.12 "0.2.0"]

Dependencies

compile (3)

Group / Artifact Type Version
org.scala-lang : scala-library jar 2.12.12
com.google.protobuf : protobuf-java jar 3.9.0
org.scala-lang : scala-reflect jar 2.12.12

Project Modules

There are no modules declared in this project.

scala-protobuf-java

Scala CI codecov Maven Central

What is this

scala-protobuf-java is a conversion tool between scala types and protobuf-java types. It can help impatient you save a lot of codes. scala-protobuf-java use scala macro to generate what you need, so it's type safe at compile time. Now you just keep free to write your code, scala-proto-java will check the error at compile time.

Import to your project

sbt (for 2.12 and 2.13. If you need more, just submit a issue or PR)

libraryDependencies += "com.github.changvvb" %% "scala-protobuf-java" % "0.2.0"

maven

<dependency>
  <groupId>com.github.changvvb</groupId>
  <artifactId>scala-protobuf-java_2.13</artifactId>
  <version>0.2.0</version>
</dependency>

How to use

Basic usage

Define case class Person

case class Person(
  id: Long,
  name: String,
  phone: Option[String],
  hobbies: Seq[String])

Define protobuf message PBPerson

message PBPerson {
    int64 id = 1;
    string name = 2;
    google.protobuf.StringValue phone = 3;
    repeated string hobbies = 4;
}

Using protoc, it will generate PBPerson.java with corresponding members. You can convert Person to PBPerson like this

val builder = PBPerson.newBuilder()
builder.setId(person.id)
builder.setName(person.name)
person.phone.foreach(p => builder.setPhone(StringValue.of(p)))
person.hobbies.foreach(builder.addHobbies)
val pbPerson:PBPerson = builder.build()

On the contrary, you can convert PBPerson to Person like this

val person1 = Person(
  pbPerson.getId,
  pbPerson.getName,
  if(pbPerson.hasPhone) Some(pbPerson.getPhone.getValue) else None,
  scala.collection.JavaConverters.iterableAsScalaIterable(pbPerson.getHobbiesList).toSeq
)

Now, we can do it with a few codes with the help of scala-protobuf-java

import pbconverts.{ Protoable, Scalable }
val convertedPBPerson:PBPerson = Protoable[Person,PBPerson].toProto(person)
val convertedPerson:Person = Scalable[Person,PBPerson].toScala(pbPerson)

More simplified

import pbconverts.ProtoScalable
val protoScalable = ProtoScalble[Person,PBPerson]
protoScalable.toProto(person)
protoScalable.toScala(pbPerson)

Or you can use implicit style

import pbconverts.{ ProtoScalable, Converter}
implicit val protoScalable = ProtoScalble[Person,PBPerson]
Converter.toProto(person)

In general, we often put the implicit value in companion object

object Person {
  implicit val protoScalable = ProtoScalble[Person,PBPerson]
}
Converter.toScala(pbPerson)

Nested structure

Define a nested case class ParentMessage

case class SubMessage(subValue:Int)
case class ParentMessage(parentValue:Int, subMessage:SubMessage)

Define a nested protobuf message PBParentMessage

message PBSubMessage {
  int32 sub_value = 1;
}

message PBParentMessage {
  int32 parent_value = 1;
  PBSubMessage sub_message = 2;
}
import pbconverts.{ Scalable, Protoable }
implicit val subProtoable = Protoable[SubMessage,PBSubMessage]
Protoable[ParentMessage, PBParentMessage].toProto(ParentMessage(...))


implicit val subScalable = Scalable[SubMessage,PBSubMessage]
Scalable[ParentMessage, PBParentMessage].toScala(PBParentMessage.newBuilder().build())

Hint: you can replace Protoable[SubMessage,PBSubMessage] and Scalable[SubMessage,PBSubMessage] with ProtoScalable[SubMessage,PBSubMessage]

Custom you own conversion

If you want use Protoable[Person, PBPerson] to convert a Person object to PBPerson object but you want custom field id. You can use ProtoableBuilder:

val customProtoable = ProtoableBuilder[Person,PBPerson]
                        .setField(_.getId, p => if (p.id < 0) 0 else p.id)
                        .build
customProtoable.toProto(Person(...))

Also, if you want convert protobuf to case class with the same logic, you can use ScalableBuilder

val customScalable = ScalableBuilder[Person,PBPerson]
                       .setField(_.id, p => if(p.getId < 0) 0 else p.id)
                       .build
customScalable.toScala(PBPerson.newBuilder().build)

Versions

Version
0.2.0
0.1.1