Home > database >  Kotlin Serialization issues: Class is not registered for polymorphic serialization in the scope of i
Kotlin Serialization issues: Class is not registered for polymorphic serialization in the scope of i

Time:07-24

I am facing issues with serialization using Kotlin. I've followed through the steps here https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serialization-guide.md but unfortunately, no luck...

This is my code:

sealed interface Convertible {

    fun convertUserInput(value : String): String
}


@Serializable
@SerialName("CustomConvertible")
class CustomConvertible(): Convertible {


    override fun convertUserInput(value : String): String {
       return ""
    }
}


@Serializable
class DTOAttribute(val convertibles         : List<Convertible>   = emptyList())

Later on, I'd like to encode the DTOAttribute with val string = Json.encodeToString(dtoAttr)

Calling this, gives me the following exception:

kotlinx.serialization.SerializationException: Class 'CustomConvertible' is not registered for polymorphic serialization in the scope of 'Convertible'.
Mark the base class as 'sealed' or register the serializer explicitly.

This confuses me, as I've marked the interface as sealed and used @Serializable.

Versions build.gradle

plugins{
    kotlin("jvm")
    kotlin("plugin.serialization") version("1.6.10")
...

sourceSets{
    named("main") {
        dependencies {
...
            api("org.jetbrains.kotlin:kotlin-reflect:1.6.10")
            api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
        }
    }
}

org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2

What else am I missing then?

CodePudding user response:

Update: you're using Kotlin 1.6.10, but KxS didn't support serializing sealed interfaces until 1.6.20

If you can update to 1.6.20 , then adding @Serializable to Convertible works.

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json


@Serializable
sealed interface Convertible {
  fun convertUserInput(value: String): String
}


@Serializable
@SerialName("CustomConvertible")
class CustomConvertible : Convertible {
  override fun convertUserInput(value: String): String {
    return ""
  }
}


@Serializable
class DTOAttribute(
  val convertibles: List<Convertible> = emptyList()
)


fun main() {
  val dtoAttribute = DTOAttribute(listOf(CustomConvertible()))

  val string = Json.encodeToString(dtoAttribute)

  println(string)
  // {"convertibles":[{"type":"CustomConvertible"}]}
}

If I remove @Serializable I get the same error that you report

//@Serializable
sealed interface Convertible {
  fun convertUserInput(value: String): String
}
Exception in thread "main" kotlinx.serialization.SerializationException: Class 'CustomConvertible' is not registered for polymorphic serialization in the scope of 'Convertible'.
Mark the base class as 'sealed' or register the serializer explicitly.

Versions

  • Kotlinx Serialization 1.3.3
  • Kotlin/JVM 1.7.10

Workaround for 1.6.10 - sealed class

If you can't update your version of Kotlin then you can convert Convertible to be a sealed class.

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json


@Serializable
sealed class Convertible {
  abstract fun convertUserInput(value: String): String
}


@Serializable
@SerialName("CustomConvertible")
class CustomConvertible : Convertible() {
  override fun convertUserInput(value: String): String {
    return ""
  }
}


@Serializable
class DTOAttribute(
  val convertibles: List<Convertible> = emptyList()
)


fun main() {
  val dtoAttribute = DTOAttribute(listOf(CustomConvertible()))

  val string = Json.encodeToString(dtoAttribute)

  println(string)
  // {"convertibles":[{"type":"CustomConvertible"}]}
}

Setup

Here's how to setup using Gradle Kotlin DSL (from the README):

// build.gradle.kts

plugins {
  kotlin("jvm") version "1.7.10" // or kotlin("multiplatform") or any other kotlin plugin
  kotlin("plugin.serialization") version "1.7.10"
}


dependencies {
  implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.3.3"))
  implementation("org.jetbrains.kotlinx:kotlinx-serialization-json")
}
  • Related