About this issue <around protobuf oneof support> ,...
# serialization
g
About this issue around protobuf oneof support , can someone explain me why "this Protobuf feature does not naturally map into Kotlin typesystem"? Feels like sealed class/interface are the same concept.
@sandwwraith I'm looking at ktx serialization to know if it's something that can be done (PR) by myself or not. I'm not sure to understand what "a lot of hand-work and checking" are referring too in the code. If you've any inputs/advise on this topic, thanks!
k
My suspicion is because Kotlin does not have proper union types. sealed interfaces/classes require you to manually wrap the underlying type. Eg.
Copy code
message SampleMessage {
  oneof test_oneof {
     string name = 4;
     SubMessage sub_message = 9;
  }
}
Could not be directly deserialized to
String | Submessage
, you’d have to create a wrapper.
Copy code
sealed interface TestOneOf {
  class Name(val name: String) : TestOneOf
  class SubMessage(val subMessage: ActualSubMessage) : TestOneOf
}
I suspect since this isn’t a perfect mapping the serialization team doesn’t want to support it
g
Feels to me like the wrapping could be an inline class there. And if in your example the class Name is inline, I don't understand why it's not a perfect mapping.
s
@glureau (is it the same handle Slack autocompletes)? The
this Protobuf feature does not naturally map into Kotlin typesystem
means that oneOf in protobuf is often used with strings and other primitives, which are not sealed classes in Kotlin. Also, polymorphism on sealed classes usually requires writing a type token into object (as it is done in Json) or into an array, while oneOf can be just a string. Moreover, oneOf is embedded directly into the message, while sealed class introduces sub-message of its own. I agree that inline wrappers in sealed interface can provide more or less accurate representation, but it requires this "a lot of hand-work and checking": • handling
AbstractPolymorphicSerializer
with a custom logic instead of default one • embedding properly the result of such polymorphic serialization • carefully checking that all indices in oneOf hierarchy make sense inside the outer message And that's only a serialization. For deserialization, there also should be a reverse mapping from index to a sealed interface inheritor.