ScalaPB's code generator provides supports many different customizations. To
get access to these customizations, you need to import
in the proto files you want to customize. You can also have the options apply
to an entire proto3 package by using package-scoped options (see below).
scalapb/scalapb.proto available to be imported in your project, add
the following SBT setting in your
If you are invoking
protoc manually, you will need to ensure that the files in
directory are available to your project.
ScalaPB file-level options lets you
- specify the name of the Scala package to use (the default is using the java package name).
- request that ScalaPB will not append the protofile name to the package name.
- specify Scala imports so custom base traits and custom types (see below) do not require the full class name.
The file-level options are not required, unless you are interested in those customizations. If you do not want to customize the defaults, you can safely skip this section.
scopecontrols whether the specified options apply only for this proto files or for the entire package. Default is
FILE. See package-scoped options for more details.
package_namesets the Scala base package name, if this is not defined, then it falls back to the
java_packageoption. If the
java_packageoption is also not the found, then the package name from file's
packagestatement is used.
flat_packageto true (default is
false) makes ScalaPB not append the protofile base name to the package name. You can also apply this option globally to all files by adding it to your ScalaPB SBT Settings.
single_fileoption makes the generator output all messages and enums to a single Scala file.
java_conversionsoptions tells ScalaPB to generate converters to the corresponding Java messages in this file. It does not automatically trigger Java source code generation for the messages. If you need to generate source code in Java, include
PB.gens.javain the list of targets in sbt-protoc.
preambleis a list of strings that is output at the top of the generated Scala file. This option requires
single_fileto be set. It is commonly used to define sealed traits that are extended using
(scalapb.message).extends- see custom base traits below and this example.
object_nameoption lets you customize the name of the generated class that contains various file-level members such as descriptors and a list of companion objects for the generated messages and enums. This is useful in case you are running into issues where the generated class name conflicts with other things in your project.
falseinhibits generation of lenses (default is
falseinhibits generation of getters (default is
trueretains information in the descriptor that can be used to retrieve source code information from the descriptor at runtime (such as comments and source code locations). This option is turned off by default to conserve source size and memory at runtime. When this option is enabled, use the
locationmethod on various descriptors to access source code information.
By default, all non-required fields have default values in the constructor of the generated case classes. When setting
trueno default values will be generated for all fields.
Typically, enum values appear in UPPER_CASE in proto files, and ScalaPB generates case objects with exactly the same name in Scala. If you would like ScalaPB to transform the names into CamelCase, set
It is a common practice in protobufs to prefix each enum value name with the name of the enum. For example, an enum name
Sizemay have values named
SIZE_LARGE. When you set
true, ScalaPB will strip the enum's name from each value name, and they would become
LARGE. Then the name can be transformed to camel-case according to
enum_value_naming. Note that the prefix that is removed is the all-caps version of the enum name followed by an underscore.
By default, during deserialization only known fields are retained. When setting
true, all generated messages in this file will preserve unknown fields. This is default behaviour in java for Proto3 messages since 3.5.0. In ScalaPB 0.10.0: the default of this field became
truefor consistency with Java.
bytes_typeto customize the Scala type used for the
bytesfield type. You will need to have an implicit
TypeMapper[com.google.protobuf.ByteString, YourType]instance so ScalaPb can convert back and forth to the type of your choice. That implicit will be found if it is defined under
YourTypecompanion object, or on a package object that matches the generated code (or any of its parent packages).
Note: this option is available in ScalaPB 0.8.2 and later.
Sometimes you want to have the same file-level options applied to all
the proto files in your project. To accomplish that, add a
file (the name does not matter) next to your proto files that looks like this:
All the options in this file will be applied to all proto files in the
com.mypackage and its sub-packages.
There is no need to explictly import this file from other protos. If you are
sbt-protoc and the file is in the proto source directory (default is
src/main/protobuf) then the file will be found and the options applied. If
you are invoking protoc in another way, you need to ensure that this
file is passed to protoc together with the rest of the files.
If you are generating Scala code for proto files that you don't own, you can
use this feature to customize code generation by creating a
file for that third-party package and include it within your proto source
The following rules are applied when validating package-scoped options:
- At most one file in each package may provide package-scoped options.
- Sub-packages may override package-scoped options provided by their parent
packages. The options are merged using the Protocol Buffers
mergeFromsemantics. Specifically, this implies that repeated fields such as
- Proto files get the most specific package-scoped options for the package
they are in. File-level options defined in a proto file get merged with the
package-level options using
- Proto files with package-scoped options must have a
packagestatement. This is to prevent the possibility of options applied globally. Standard classes that are shipped with ScalaPB already assume certain options, so overriding options globally may lead to compilation errors.
If you are publishing a library that includes protos with package-scoped options, you need to make sure your library users source the package-scoped option proto file so the customizations are applied when they generate code.
Your users can simply import your package-scoped options from any proto file in their project to have the settings applied (a single import of the package-scoped options file would apply it globally for the code generator). However, since ScalaPB 0.10.11 and sbt-protoc 1.0.1, sbt-protoc provides a way to automate this with no need to manually import the package-scoped options file. This is accomplished by including a special attribute in the manifest of the library you publish. Add the following to your library's settings:
The path above is relative to the root directory of the published JAR (so
src/main/protobuf is not needed). Users add your library to their projects like this:
The first dependency provides the precompiled class files. The second dependency makes it possible
for users to import the protos in the jar file.
sbt-protoc will look for the
ScalaPB-Options-Proto attribute in the jar's manifest and automatically add the package scoped options file
to the protoc command line.
Since the package-scoped options file is used as a source file in multiple projects, it should not define any types (messages, enums, services). This ensures that the package-scoped proto file does not generate any code on its own so we don't end up with duplicate class files.
As a consumer of third-party dependencies that come with options proto, you can disable the behavior of automatically adding the options proto to protoc by setting
in sbt. In that case, it is your responsibility to either manually
import the option protos in one
of your own project source files so it gets applied, or ensure that the
generator settigs used in your project are consistent with the ones used to
generate the dependency. Differences in settings can lead to generated code
that does not compile.
In some situations, you may want to set some options in a proto file, but without modifying the original proto file or adding anything ScalaPB-specific to it. To accomplish that, you can define auxiliary options under package-scoped options.
For example, if you are given this proto file:
You can add a file
package.proto with the following content:
aux_message_options contains options targeted at different messages define under the same proto package of the package-scoped options. The
target name needs to be fully-qualified message name in the protobuf namespace. Similar to
aux_message_options, we also have
aux_field_options. See example usage here.
In proto 3, unlike proto 2, primitives are not wrapped in an option by default.
The standard technique to obtain an optional primitive is to wrap it inside a
message (since messages are provided inside an
Option). Google provides
standard wrappers to the primitive types in
primitive_wrappers is enabled by default for ScalaPB>=0.6.0. Whenever one
of the standard wrappers is used, it will be mapped to
is a primitive type. For example:
To disable primitive wrappers in a file:
In versions of ScalaPB prior to 0.6.0, primitive wrappers had to be turned on manually in each file:
Note: this option is available in ScalaPB 0.6.1 and later.
ScalaPBs allows you to specify custom base traits to a generated case class. This is useful when you have a few messages that share common fields and you would like to be able to access those fields through a single trait.
In your code, define the base trait
DomainEvent and include any subset of the fields:
You can specify any number of base traits for a message.
It is also possible to make the generated companion classes extend a class
or trait, by using the
companion_extends option. For example:
Will generate a case class that extends
MySuperClass, and the companion
object will extend
Note: this option is available in ScalaPB 0.9.0 and later.
Use the following option to define one or more base traits for a generated SealedOneof:
In a similar fashion to custom base traits for messages, it is possible to define custom base traits for enum types, for the companion objects of enum types and even for specific values.
The generated code will look something like this:
You can customize the Scala type of any field. One use-case for this is when
you would like to use type-safe wrappers around primitive values to enforce unit
correctness. For example, instead of using a raw integer for time fields, you can
wrap them in a
We would like to write code like this:
How will ScalaPB know how to convert from the original type (
Integer) to the
Seconds? For each custom type you need to define an implicit
TypeMapper that will tell ScalaPB how to convert between the custom type and
the base Scala type. A good place to define this implicit is in the companion
class for your custom type, since the Scala compiler will look for a
typemapper there by default. If your typemapper is defined elsewhere, you
will need to import it manually by using the
import file-level option.
TypeMapper takes two function parameters. The first converts from the original type to
the custom type. The second function converts from the custom type to the
In addition to primitive values, you can customize enums and messages as well.
For more examples, see:
If you have a TypeMapper that maps a generated type into a type you don't own
String, or a third-party class) then you don't have access to the
companion object to define the typemapper in. Instead, you can place the
typemapper in one of the parent package objects of the generated code. For
example, if you want to map an enum to a string, and the message containing it
goes into the
a.b.c package, you can define the type mapper like this:
In the previous section you saw how to customize the type generated for a
specific field. ScalaPB also lets you specify a custom type at the message
type is set at the message level, that type is used for all the
fields that use that message. This eliminates the need to specify
type on each field
of this type.
In a Scala file define an implicit mapper:
Now, each time you reference
Duration in a proto file, the generated field in Scala code
will be of type
If you do not want any instance of your message to be boxed (regardless if it
has a custom type), you can set
no_box at the message-level:
Then when this message is used, it will not be wrapped in an
no_box is specified at the field level, it overrides the value specified at
the message level.
Since version 0.6.0 it is possible to customize the key and value types of
maps. Like the custom types described above you will need to have a
for the custom type.
CustomMaps in maps.proto
You can also customize the collection type used for a map. See the next section for details.
By default, ScalaPB compiles repeated fields into a
Seq[T]. When a message
is parsed from bytes, the default implementation instantiates a
which is a subtype of
Seq[T]. You can instruct ScalaPB to use a different
collection type for one field by specifying the
collection_type option. You
can also specify a
collection_type for the entire proto file by specifying a
collection_type at the file-level.
If both are defined then the field-level setting wins.
collection_type, we have
map_type for map types. By default,
scala.collection.immutable.Map for maps, and you can
customize it at the field level, or file-level by specifying a
map_type was introduced in ScalaPB 0.8.5.
Note on mutable collection: ScalaPB assumes that all data is immutable. For example, the result
serializedSize is cached in a private field. When choosing mutable collections, you must be
careful not to mutate any collection after it has been passed to any message, or you might get some
Array is not supported along with Java conversions.
Note: Most Scala collections can be used with this feature. If you are trying
to implement your own collection type, it may be useful to check
MyMap, the simplest custom collection that is compatible with ScalaPB:
Sometimes it may be useful to manually specify the name of a field in the
generated code. For example, if you have a field named
hash_code, then the
camel-case version of it would be
hashCode. Since that name would conflict with
we inherit from Java, ScalaPB issues an error. You can tell ScalaPB to use an
alternative name by using the
It is also possible to customize the Scala name of an enum value:
The same customization can be applied to
Since ScalaPB 0.6.3, you can add annotations to the generated case classes like this:
In ScalaPB 0.7.0, you can add annotations to the companion object of a message and to individual fields:
In ScalaPB 0.10.9, you can also add annotations to the auto generated unknownFields field:
In ScalaPB 0.11.4, you can also add annotations to the enum values and the
Unrecognized case class: