class ProtoBuf : BinaryFormat
Implements encoding and decoding classes to/from bytes using Proto2 specification. It is typically used by constructing an application-specific instance, with configured specific behaviour and, if necessary, registered custom serializers (in SerialModule provided by context constructor parameter).
Given a ProtoBuf definition with one required field, one optional field and one optional field with a custom default value:
message MyMessage {
required int32 first = 1;
optional int32 second = 2;
optional int32 third = 3 [default = 42];
}
The corresponding Serializable class should match the ProtoBuf definition and should use the same default values:
@Serializable
data class MyMessage(val first: Int, val second: Int = 0, val third: Int = 42)
By default, protobuf fields ids are being assigned to Kotlin properties in incremental order, i.e. the first property in the class has id 1, the second has id 2, and so forth. If you need a more stable order (e.g. to avoid breaking changes when reordering properties), provide custom ids using ProtoId annotation.
By default, all numbers are encoded using varint encoding. This behaviour can be changed via ProtoNumberType annotation.
Lists are represented as repeated fields. Because format spec says that if the list is empty,
there are no elements in the stream with such tag, you must explicitly mark any
field of list type with default = emptyList(). Same for maps.
There's no special support for oneof
protobuf fields. However, this implementation
supports standard kotlinx.serialization's polymorphic and sealed serializers,
using their default form (message of serialName: string and other embedded message with actual content).
This implementation does not support repeated packed fields, so you won't be able to deserialize
Proto3 lists. However, other messages could be decoded. You have to remember that since fields in Proto3
messages by default are implicitly optional,
corresponding Kotlin properties have to be nullable with default value null
.
// Serialize to ProtoBuf hex string
val encoded = ProtoBuf.dumps(MyMessage.serializer(), MyMessage(15)) // "080f1000182a"
// Deserialize from ProtoBuf hex string
val decoded = ProtoBuf.loads<MyMessage>(MyMessage.serializer(), encoded) // MyMessage(first=15, second=0, third=42)
// Serialize to ProtoBuf bytes (omitting default values)
val encoded2 = ProtoBuf(encodeDefaults = false).dump(MyMessage.serializer(), MyMessage(15)) // [0x08, 0x0f]
// Deserialize ProtoBuf bytes will use default values of the MyMessage class
val decoded2 = ProtoBuf.load<MyMessage>(MyMessage.serializer(), encoded2) // MyMessage(first=15, second=0, third=42)
Null values can be used as the default value for optional fields to implement more complex use-cases that rely on
checking if a field was set or not. This requires the use of a custom ProtoBuf instance with
ProtoBuf(encodeDefaults = false)
.
@Serializable
data class MyMessage(val first: Int, private val _second: Int? = null, private val _third: Int? = null) {
val second: Int
get() = _second ?: 0
val third: Int
get() = _third ?: 42
fun hasSecond() = _second != null
fun hasThird() = _third != null
}
// Serialize to ProtoBuf bytes (encodeDefaults=false is required if null values are used)
val encoded = ProtoBuf(encodeDefaults = false).dump(MyMessage(15)) // [0x08, 0x0f]
// Deserialize ProtoBuf bytes
val decoded = ProtoBuf.load<MyMessage>(MyMessage.serializer(), encoded) // MyMessage(first=15, _second=null, _third=null)
decoded.hasSecond() // false
decoded.second // 0
decoded.hasThird() // false
decoded.third // 42
// Serialize to ProtoBuf bytes
val encoded2 = ProtoBuf(encodeDefaults = false).dumps(MyMessage.serializer(), MyMessage(15, 0, 0)) // [0x08, 0x0f, 0x10, 0x00, 0x18, 0x00]
// Deserialize ProtoBuf bytes
val decoded2 = ProtoBuf.loads<MyMessage>(MyMessage.serializer(), encoded2) // MyMessage(first=15, _second=0, _third=0)
decoded.hasSecond() // true
decoded.second // 0
decoded.hasThird() // true
decoded.third // 0
encodeDefaults
- specifies whether default values are encoded.
context
- application-specific SerialModule to provide custom serializers.
(common, js, jvm, native)
Default |
companion object Default : BinaryFormat |
(common, js, jvm, native)
<init> |
Implements encoding and decoding classes to/from bytes using Proto2 specification. It is typically used by constructing an application-specific instance, with configured specific behaviour and, if necessary, registered custom serializers (in SerialModule provided by context constructor parameter). <init>(encodeDefaults: Boolean = true, context: SerialModule = EmptyModule) |
(common, js, jvm, native)
context |
application-specific SerialModule to provide custom serializers. val context: SerialModule |
(common, js, jvm, native)
encodeDefaults |
specifies whether default values are encoded. val encodeDefaults: Boolean |
(common, js, jvm, native)
dump |
Serializes value to ByteArray using given serializer. fun <T> dump(serializer: SerializationStrategy<T>, value: T): ByteArray |
(common, js, jvm, native)
load |
Deserializes given bytes to an object of type T using given deserializer. fun <T> load(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T |