6
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?

  • Have you tried: `data class Theory(id: String):Exercise(id)` ? – amanin Jul 31 '20 at 06:06
  • 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 Jul 31 '20 at 08:03

1 Answers1

11

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.

Oliver O.
  • 641
  • 3
  • 9