Just trying to understand Kotlin Serialization a bit better, then I couldn't figure out what went wrong.
Here's the code, just a simple encode and decode.
open class Human(private val uuid: UUID = UUID.randomUUID())
@Serializable
class User(val name: String, val age: Int) : Human()
@Test
fun decodeEncodeSerialization() {
val user = User(
"Aerith Gainsborough",
25
)
val userJson = JSON.stringify(User.serializer(), user)
val userObject = JSON.parse(User.serializer(), userJson)
}
kotlinx.serialization.SerializationException: Can't locate argument-less serializer for class java.util.UUID (Kotlin reflection is not available). For generic classes, such as lists, please provide serializer explicitly.
Here's the problem with the UUID class, if I'm using a String. It'll be fine.
Is it because java.util.UUID implements java.io.Serializable?
Any idea what went wrong here?
It's telling you what's wrong. You need to provide a custom serializer than can convert UUID to a primitive that exists in JSON (such as string). Details are here: https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/custom_serializers.md
Managed to got it to work. Just gonna put here for future references.
Thanks mate!
@Serializable
open class Human(
@Serializable(with = UUIDSerializer::class)
var uuid: UUID = UUID.randomUUID()
)
@Serializer(forClass = UUID::class)
object UUIDSerializer : KSerializer<UUID> {
override val descriptor: SerialDescriptor
get() = StringDescriptor.withName("UUID")
override fun serialize(output: Encoder, obj: UUID) {
output.encodeString(obj.toString())
}
override fun deserialize(input: Decoder): UUID {
return UUID.fromString(input.decode())
}
}
@Serializable
class User(val name: String, val age: Int) : Human()
@Test
fun decodeEncodeSerialization() {
val user = User("Aerith Gainsborough", 25)
val userJson = JSON.stringify(User.serializer(), user)
val userObject = JSON.parse(User.serializer(), userJson)
}
Since last comment there were a lot of signatures changed, so the current UUID Serializer is:
@ExperimentalSerializationApi
@Serializer(forClass = UUID::class)
object UUIDSerializer : KSerializer<UUID> {
override val descriptor: SerialDescriptor
get() = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: UUID) {
encoder.encodeString(value.toString())
}
override fun deserialize(decoder: Decoder): UUID {
return UUID.fromString(decoder.decodeString())
}
}
Most helpful comment
Managed to got it to work. Just gonna put here for future references.
Thanks mate!