I'm playing around with the Protobuf encoding for ...
# serialization
r
I'm playing around with the Protobuf encoding for kotlinx-serialization. The main thing I'm interested in understanding how it works is with polymorphism. For example, one use case is a classic sealed
SomeResult
type with
Success
and
Failure
subtypes. Obviously these subtypes have different fields. I see that there is OneOf support [1] but the docs give a simplistic example with the same single field type, across both subclass types, which wouldn't work for most use cases including the
SomeResult
type mentioned. When I try to serialize this, I get the error:
Copy code
Implementation of oneOf type Foo should contain only 1 element, but get 4
(
Foo
here is one of the two subtypes). I don't believe Protobuf limits OneOf fields in this way, but I'm not super-familiar with Protobufs in general, so I could be wrong. Can someone shed some light here? [1] https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/formats.md#oneof-field-experimental
e
if you want something like
Copy code
message Data {
    required string name = 1;
    oneof phone {
        HomePhone home_phone = 2;
        WorkPhone work_phone = 3;
    }
}
message HomePhone { ... }
message WorkPhone { ... }
in protobuf, then I think you'll need
Copy code
@Serializable
data class Data(
    @ProtoNumber(1) val name: String,
    @ProtoOneOf val phone: IPhoneType?,
)

@Serializable
sealed interface IPhoneType

@Serializable
class HomePhoneType(
    @ProtoNumber(2) val homePhone: HomePhone,
): IPhoneType

@Serializable
class WorkPhoneType(
    @ProtoNumber(3) val workPhone: WorkPhone,
): IPhoneType
@Serializable

@Serializable
class HomePhone(...)

@Serializable
class WorkPhone(...)
in kxs
r
Ah, thank you. Do you know if there is a reason the intermediate type classes are needed? It seems the only value they add is in defining the
ProtoNumber
for the type, but couldn't an annotation on the subclass type be used for that value instead?
The generated protobuf schema has no trace of the intermediate types:
Copy code
syntax = "proto2";


// serial name 'Data'
message Data {
  required string name = 1;
  oneof phone {
    HomePhone homePhone = 2;
    WorkPhone workPhone = 3;
  }
}

// serial name 'HomePhone'
message HomePhone {
  required string foo = 1;
}

// serial name 'WorkPhone'
message WorkPhone {
  required string bar = 1;
}
I created https://github.com/Kotlin/kotlinx.serialization/issues/2918 -- feel free to upvote and/or comment.