Bohdan Yevtushenko
Bohdan Yevtushenko

Reputation: 151

How to serialize kotlin sealed class with open val using kotlinx serialization

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

Answers (3)

Buntupana
Buntupana

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

Nandha Kumar
Nandha Kumar

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

Oliver O.
Oliver O.

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

Related Questions