kotlinx.serialization
kotlinx.serialization copied to clipboard
Incorrect deserialization of sealed class
Describe the bug
I'm using the kotlin serialization properties (not the json) and I'm getting MissingFieldException error when I try to decode a sealed class from a map
To Reproduce
I have a map
// my sealed classes
@Serializable
@Keep
sealed class Odds {
abstract val value: Long
}
@SerialName("EUROPEAN")
@Serializable
@Keep
data class European(override val value: Long) : Odds()
@SerialName("AMERICAN")
@Serializable
@Keep
data class American(override val value: Long) : Odds()
val map = mapOf("type" to "AMERICAN", "value" to 1)
val odds: Odds = Properties.decodeFromMap(map)
This is the stracktrace I have
Caused by: kotlinx.serialization.MissingFieldException: Field 'value' is required for type with serial name 'AMERICAN', but it was missing
at kotlinx.serialization.internal.PluginExceptionsKt.throwMissingFieldException(PluginExceptions.kt:20)
at br.com.mob1st.bet.features.competitions.domain.American.<init>(Bet.kt:36)
at br.com.mob1st.bet.features.competitions.domain.American$$serializer.deserialize(Bet.kt:36)
at br.com.mob1st.bet.features.competitions.domain.American$$serializer.deserialize(Bet.kt:36)
at kotlinx.serialization.encoding.Decoder$DefaultImpls.decodeSerializableValue(Decoding.kt:257)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableValue(Tagged.kt:178)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableValue(Tagged.kt:207)
at kotlinx.serialization.internal.TaggedDecoder$decodeSerializableElement$1.invoke(Tagged.kt:280)
at kotlinx.serialization.internal.TaggedDecoder.tagBlock(Tagged.kt:297)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement(Tagged.kt:280)
at kotlinx.serialization.encoding.CompositeDecoder$DefaultImpls.decodeSerializableElement$default(Decoding.kt:533)
at kotlinx.serialization.internal.AbstractPolymorphicSerializer.deserialize(AbstractPolymorphicSerializer.kt:57)
at kotlinx.serialization.encoding.Decoder$DefaultImpls.decodeSerializableValue(Decoding.kt:257)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableValue(Tagged.kt:178)
at kotlinx.serialization.properties.Properties.decodeFromMap(Properties.kt:173)
at br.com.mob1st.bet.features.competitions.data.ContestMapperKt$nodeBuilder$1.invoke(ContestMapper.kt:226)
at br.com.mob1st.bet.features.competitions.data.ContestMapperKt$nodeBuilder$1.invoke(ContestMapper.kt:33)
at br.com.mob1st.bet.features.competitions.data.CompetitionCollection.getConfrontationsById(CompetitionCollection.kt:54)
at br.com.mob1st.bet.features.competitions.data.CompetitionCollection$getConfrontationsById$1.invokeSuspend(Unknown Source:12)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:33)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:102)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Expected behavior The deserialization should run properly Environment
- Kotlin version: 1.7.0
- Library version: 1.4.0
- Kotlin platforms: Android
- Gradle version: gradle-7.4
- IDE version Android Studio dolphin
- Other relevant context [e.g. OS version, JRE version, ... ]: I tried to debug the the lib code to figure out where are the cause of the problem, and it seems that for some reason the
NamedValueDecoderare returnvalue.valuein the getTag method
important info: If I try the same thing using the kotlinx-serialization-json it works perfectly
val oddsMap = mapOf(
"type" to JsonPrimitive("AMERICAN"),
"value" to JsonPrimitive(1L)
)
val e = JsonObject(
oddsMap
)
val odds: Odds = Json {
ignoreUnknownKeys = true
}.decodeFromJsonElement(e)