-
Notifications
You must be signed in to change notification settings - Fork 50
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
IllegalStateException: Must call beginStructure() and use returned Decoder when using @Contextual
#568
Comments
Have you followed the instructions in the error message? You need to modify |
Hi @charleskorn, I've been trying for about an hour to get a Serializer to work with import kotlinx.serialization.Contextual
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encodeToString
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import java.time.LocalDate
import kotlin.test.Test
import kotlin.test.assertEquals
class ConfigTest {
private val json: Json = Json {
serializersModule = SerializersModule {
contextual(LocalDate::class, LocalDateSerializer)
}
}
@Test
fun `Test serialization and deserialization`() {
val config = Config(
dateOfBirth = LocalDate.parse("1980-01-01"),
)
val jsonString = json.encodeToString(config)
assertEquals(config, json.decodeFromString(Config.serializer(), jsonString))
}
}
@Serializable
data class Config(
@Contextual
val dateOfBirth: LocalDate,
)
object LocalDateSerializer : KSerializer<LocalDate> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDate) {
encoder.encodeString(value.toString())
}
override fun deserialize(decoder: Decoder): LocalDate {
val string = decoder.decodeString()
return LocalDate.parse(string)
}
} Any idea why it's not playing nice with |
Hi, I looked at this more closely - from my perspective, the Yaml decoder incorrectly handles cases when a descriptor has
If I understood this correctly, we need to call descriptor.kind is SerialKind.CONTEXTUAL -> YamlInput.createFor(node, yaml, context, configuration, context.getContextualOrThrow(descriptor))
private fun SerializersModule.getContextualOrThrow(
descriptor: SerialDescriptor
): SerialDescriptor = getContextualDescriptor(descriptor) ?: error("contextual serializer for type ${descriptor.capturedKClass} was not found") Also, I have found some strange usage of |
Describe the bug
yaml.decodeFromString()
throws anIllegalStateException: Must call beginStructure() and use returned Decoder
when using the@Contextual
annotation on a propertyReproduction repo
Steps to reproduce
Run the test
Test serialization and deserialization
Expected behaviour
The data class
is correctly encoded and decoded.
Actual behaviour
The data class
Config
is correctly encoded (dateOfBirth: "1980-01-01"
) but, when decoded it throws anIllegalStateException
.Version information
Any other information
Using
instead of
works around the issue but it would be nice to be able to use the
@Contextual
annotation.The text was updated successfully, but these errors were encountered: