Hi, i don't really get SerialDescriptor things. I ...
# serialization
s
Hi, i don't really get SerialDescriptor things. I would be grateful if someone could code review my code below and tell me if i do something terribly wrong. My problem is that abstract objects are boxed inside of object which contains information about their type. But after deserialization i do not want to always unbox my object manually. I feel like I should use
polymorphic
but i not sure if it was intended for such cases. Current working code below:
Copy code
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.encoding.decodeStructure
import kotlinx.serialization.json.Json
import org.junit.Assert
import org.junit.Test

class WSampleTest {
    val parser = Json {
        isLenient = true
        ignoreUnknownKeys = true
        allowSpecialFloatingPointValues = true
        useArrayPolymorphism = false
    }

    @Test
    fun shouldParseFirst() {
        val string = """{"type":"first", "data":{"name":"test"}}"""
        val firstObj = parser.decodeFromString(CustomClassObjSerializer, string)
        Assert.assertEquals(CustomClassSpecificFirst("test"), firstObj)
    }

    @Test
    fun shouldParseSecond() {
        val string = """{"type":"second", "data":{"otherName":"otherTest"}}"""
        val firstObj = parser.decodeFromString(CustomClassObjSerializer, string)
        Assert.assertEquals(CustomClassSpecificSecond("otherTest"), firstObj)
    }
}


@Serializer(forClass = CustomClassObj::class)
object CustomClassObjSerializer : KSerializer<CustomClassObj> {

    override val descriptor: SerialDescriptor = CustomClassBoxWithType.serializer().descriptor

    override fun deserialize(decoder: Decoder): CustomClassObj {
        decoder.decodeStructure(descriptor) {
            decodeElementIndex(descriptor)
            val serializer = when (decodeStringElement(descriptor, 0)) {
                "first" -> CustomClassSpecificFirst.serializer()
                "second" -> CustomClassSpecificSecond.serializer()
                else -> UnknownMessage.serializer()
            }
            decodeElementIndex(descriptor)
            return decodeSerializableElement(
                descriptor,
                1,
                serializer
            )
        }
    }

    override fun serialize(encoder: Encoder, value: CustomClassObj) =
        throw IllegalStateException("serialize is not supported")
}


@Serializable
data class CustomClassBoxWithType(val type: String, val data: CustomClassObj)

@Serializable
abstract class CustomClassObj

@Serializable
data class CustomClassSpecificFirst(val name: String) : CustomClassObj()

@Serializable
data class CustomClassSpecificSecond(val otherName: String) : CustomClassObj()

@Serializable
object UnknownMessage : CustomClassObj()