Reputation: 151
import kotlinx.serialization.Serializable
@Serializable
sealed class Exercise(open val id: String) {
@Serializable
data class Theory(override val id: String) : Exercise(id)
}
I have such kind of sealed class in my code, and compiler says me:
Serializable class has duplicate serial name of property 'id', either in the class itself or its supertypes
.
Is there way to have open val in serializable sealed class, which works correctly when overriding it?
Upvotes: 13
Views: 10224
Reputation: 1023
In my case I had some initialized properties in the sealed class constructor so I had to apply a workaround like this:
import kotlinx.serialization.Serializable
@Serializable
sealed class Exercise(
val id: String = ""
) {
@Serializable
data class None() : Exercise()
@Serializable
data class Theory(private val _id: String) : Exercise(_id)
}
Not the most beautiful way but it works
Upvotes: 0
Reputation: 365
Though abstract
property is a great way to deal with this, you can also take advantage of sealed interface
which helps solving this in a more concise way
import kotlinx.serialization.Serializable
@Serializable
sealed interface Exercise {
val id: String
@Serializable
data class Theory(override val id: String) : Exercise
}
Upvotes: 2
Reputation: 711
This is Kotlin issue KT-38958. It seems to be a corner case of the Constructor properties requirement.
It can be solved by using the following implementation,
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
@Serializable
sealed class Exercise {
abstract val id: String
@Serializable
data class Theory(override val id: String) : Exercise()
}
fun main() {
val t1 = Exercise.Theory("t1")
val t1Json = Json.encodeToString(t1)
println(t1Json)
println(Json.decodeFromString<Exercise.Theory>(t1Json).toString())
}
which will output:
{"id":"t1"}
Theory(id=t1)
For details, see "Designing serializable hierarchy" in the Kotlin Serialization Guide.
Upvotes: 17