-
Notifications
You must be signed in to change notification settings - Fork 653
Description
Describe the bug
When testing app build before release, I noticed error in deserializing response from server.
I'm not sure about root cause, but seems that minification influence the logic behind @JsonClassDiscriminator
.
When custom @JsonClassDiscriminator("entity")
set for parent (sealed) class, Json still trying to find sub-class for fields with name "type" in child classes. Basically, in nested classed Json serializer still checking for "type" fields, even thou top hierarchy defines discriminator as "entity".
In debug build - there is no error and everything works.
@Serializable
@JsonClassDiscriminator("entity")
sealed class A
@Serializable
@SerialName("child1")
data class A_Child1(
type: Any,
)
To Reproduce
In my code (simplified):
@Serializable
data class SyncResponseBody(
val t: Long,
val data: List<SyncEntity>,
)
@OptIn(ExperimentalSerializationApi::class)
@JsonClassDiscriminator("entity")
@Serializable
sealed class SyncEntity
@Serializable
@SerialName("category")
data class SyncCategory(
val id: Long,
val type: Category.Type, // enum class
) : SyncEntity()
@Serializable
data class Category(...) {
enum class Type {
ATYPE, BTYPE, CTYPE,
}
}
Network module:
@Provides
@Singleton
fun provideJson(): Json = Json {
encodeDefaults = true
ignoreUnknownKeys = true
}
With input data:
{"entity":"category","id":737,"type":"ATYPE"}
Everything works fine in debug build.
But when launching app in release variant with isMinifyEnabled = true
and
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")
// proguard-rules.pro are empty
There is error:
Serializer for subclass 'ATYPE' is not found in the polymorphic scope of 'B'. // obfuscated B = SyncEntity
Check if class with serial name 'ATYPE' exists and serializer is registered in a corresponding SerializersModule.
To temporary fix the issue, I added descriptor to Json constructor:
@Provides
@Singleton
fun provideJson(): Json = Json {
encodeDefaults = true
ignoreUnknownKeys = true
classDiscriminator = "entity" <! -- added
}
After that - serialization works normal again even in release build.
I did one more experiment. Setup:
@Provides
@Singleton
fun provideJson(): Json = Json {
encodeDefaults = true
ignoreUnknownKeys = true
classDiscriminator = "entity"
}
@OptIn(ExperimentalSerializationApi::class)
@JsonClassDiscriminator("nonsense") <! -- definitely not a discriminator in JSON
@Serializable
sealed class SyncEntity
@Serializable
@SerialName("category")
data class SyncCategory // everything else stay the same
And it works with minifyEnabled = true and release build. Discriminator in @JsonClassDiscriminator simply ignored.
But when I switch to debug build - serialization fails on kotlinx.serialization.json.internal.JsonDecodingException: Class discriminator was missing and no default serializers were registered in the polymorphic scope of 'SyncEntity'.
I truly do not understand why behavior is different in debug and release variants.
Expected behavior
@JsonClassDiscriminator()
is working in the same way before and after minification.
Environment
- Kotlin version: 2.2.0
- Library version: 1.9.0
- Imports:
org.jetbrains.kotlinx:kotlinx-serialization-core:1.9.0
andorg.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0
- Kotlin platforms: JVM, Android
- Gradle version: Android Gradle Plugin 8.11.1
- Other relevant context [e.g. OS version, JRE version, ... ] I will provide any additional info on request