@SerialId does not affect enum members
See original GitHub issueThere appears to be an incorrect enum index/value check during protobuf enum decoding (kotlin: 1.3.20, kotlinx.serialization: 0.10.0)
For example using the following .proto definition to generate the incoming serialized message:
syntax = "proto3";
package example;
option java_package = "example.java";
option java_multiple_files = true;
enum EnumA {
reserved 2 to 9;
A_ZERO = 0;
A_ONE = 1;
A_TEN = 10;
}
enum EnumB {
B_ZERO = 0;
B_ONE = 1;
B_TWO = 2;
}
message ExampleEnumMessage {
EnumA a = 1;
EnumB b = 2;
}
Deserializing to the following data class:
enum class EnumA {
@SerialId(0) A_ZERO,
@SerialId(1) A_ONE,
@SerialId(10) A_TEN;
companion object {
val defaultValue: EnumA = EnumA.values()[0]
}
}
enum class EnumB {
@SerialId(0) B_ZERO,
@SerialId(1) B_ONE,
@SerialId(2) B_TWO;
companion object {
val defaultValue: EnumB = EnumB.values()[0]
}
}
@Serializable
data class ExampleEnumMessage(
@SerialId(1) @Optional val a: EnumA = EnumA.defaultValue,
@SerialId(2) @Optional val b: EnumB = EnumB.defaultValue) {
}
The following example uses protobuf-java runtime to generate the encoded data to be decoded by kotlinx.serialization:
fun example() {
val parser = ExampleEnumMessageJava.parser()
val serializer = ExampleEnumMessage.serializer()
val message = ExampleEnumMessageJava.newBuilder().setA(EnumAJava.A_TEN).build()
// Replacing previous line with the following will not have an error.
// val message = ExampleEnumMessageJava.newBuilder().setB(EnumBJava.B_TWO).build()
val encodedWithJava = message.toByteArray()
val decodedWithKotlin = ProtoBuf.load(serializer, encodedWithJava)
}
will fail with:
java.lang.IllegalStateException: 10 is not among valid example.EnumA choices, choices size is 3
at kotlinx.serialization.internal.CommonEnumSerializer.deserialize(Enums.kt:46)
at kotlinx.serialization.protobuf.ProtoBuf$ProtobufReader.decodeSerializableValue(ProtoBuf.kt:204)
at kotlinx.serialization.TaggedDecoder$decodeSerializableElement$1.invoke(Tagged.kt:254)
at kotlinx.serialization.TaggedDecoder.tagBlock(Tagged.kt:267)
at kotlinx.serialization.TaggedDecoder.decodeSerializableElement(Tagged.kt:254)
It looks like the decoded value is directly used as the index value into an enum-value choice array, which is causing the range-check condition to fail.
What is the correct way to pass in enum constant information such that it matches the analogous protobuf IDL declaration?
Edited:
- Removed red-herring information on a application-supplied ‘value’ property in the enum class definitions. The example now attempts to tag each enum value with a
@SerialId
(though probably incorrectly used).
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (3 by maintainers)
Top Results From Across the Web
How to ensure consistency of enums in Java serialization?
The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form....
Read more >Serialization Rules - CodeNarc
The process by which enum constants are serialized cannot be customized; ... declaring class–serialVersionUID fields are not useful as inherited members.
Read more >"serialVersionUID" should not be declared blindly
Providing a serialVersionUID field on Serializable classes is strongly recommended by the Serializable documentation but blindly following that recommendation ...
Read more >Java Object Serialization Specification: 1 - System Architecture
The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form....
Read more >ALWAYS assign enum values (at least, if you serialize them)
With that little change, they've broken the whole UnityAds integration. No ads will show up anymore, because it uses the wrong AdNetwork that ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
This is the current
enum
s limitation: no serial annotation has any effect on them. We are going to fix this at some point in the future.Looking forward it. Actually, values in enums should be easier to be customized any way you like, instead of just in sequence.
I noticed that
Int
may replace the enum type, however, to make a workaround.