-
Notifications
You must be signed in to change notification settings - Fork 623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Protobuf oneOf #67
Comments
Not in the near future, since they this Protobuf feature does not naturally map into Kotlin typesystem. |
Perhaps they can be implemented by sealed classes, but that way requires a lot of hand-work and checking |
Is there a workaround for working with proto definitions which have oneOf? |
@s-garg For example, given this proto:
You can deserialize it using:
|
@bezmax you are right but for serialize i have to do this:
😭 😭 😭 |
For anybody else who runs into this issue and wants to use sealed classes: if your |
Here's an updated version for people that want protobuf polymorphic support. import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.protobuf.ProtoNumber
import kotlin.test.Test
import kotlin.test.assertEquals
@Test
fun testSealedInterface() { // Put this function in a class in test sources.
val module = SerializersModule {
polymorphic(TestOneOf::class) {
subclass(TestText::class)
subclass(TestInt::class)
}
}
val protobuf = ProtoBuf { serializersModule = module }
TestText(id = "abc", "Kotlin!").let<TestOneOf, _> { initial ->
val byteArray = protobuf.encodeToByteArray(initial)
val deserialized = protobuf.decodeFromByteArray<TestOneOf>(byteArray)
deserialized.shouldBeInstanceOf<TestText>()
deserialized.text shouldBe "Kotlin!"
}
TestInt(id = "abc", 7).let<TestOneOf, _> { initial ->
val byteArray = protobuf.encodeToByteArray(initial)
val deserialized = protobuf.decodeFromByteArray<TestOneOf>(byteArray)
deserialized.shouldBeInstanceOf<TestInt>()
deserialized.number shouldBe 7
}
}
@Serializable
sealed interface TestOneOf
@Serializable
data class TestText(
@ProtoNumber(1) val id: String,
@ProtoNumber(4) val text: String
) : TestOneOf
@Serializable
data class TestInt(
@ProtoNumber(1) val id: String,
@ProtoNumber(9) val number: Int
) : TestOneOf |
Wait, it also works if I use the unedited default Has this now been resolved? Or is there some other trick that makes it work? |
Looks like having the I think the most important question is: is that using Protobuf's |
I need to declare kotlin data class for proto structure by a custome code-gen plugin. The workaround provided above is not suitable for my case because there may be more than 1 oneof field in the protocol message, and the generated classes will be exponential. I come up with an idea, but need some help to support by the library. Let's say I have a proto message like
My favourite data class will be data class Person(
val name: String,
val phone: IPhoneType,
)
sealed interface IPhoneType
data class MobilePhone(val value: String): IPhoneType
data class HomePhone(val value: String): IPhoneType So I need to tell the ProtoBuf Decoder that if it comes with ProtoNum 2 or 3, deserialize it as A custom serializer for the whole data class Person(
@ProtoNum(1) val name: String,
@ProtoOneOfFields(2, 3) val phone: IPhoneType,
)
sealed interface IPhoneType
@ProtoOneOfNum(2)
data class MobilePhone(val value: String): IPhoneType
@ProtoOneOfNum(3)
data class HomePhone(val value: String): IPhoneType
|
Is support planned for protobufs
oneOf
? https://developers.google.com/protocol-buffers/docs/proto#using-oneofThe text was updated successfully, but these errors were encountered: