3
votes
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?

1
Have you tried: data class Theory(id: String):Exercise(id) ? - amanin
I can't do so with data classes (because constructor must have only property (val / var) parameters), but even if I do it with class Theory(id: String) : Exercise(id) instead, I have this error: This class is not serializable automatically because it has primary constructor parameters that are not properties - Bohdan Yevtushenko

1 Answers

3
votes

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.