All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonTest.kotlinx.serialization.features.PolymorphismTest.kt Maven / Gradle / Ivy

There is a newer version: 1.7.3
Show newest version
/*
 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.serialization.features

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
import kotlinx.serialization.test.*
import kotlin.test.*

class PolymorphismTest : JsonTestBase() {

    @Serializable
    data class Wrapper(
        @Id(1) @Polymorphic val polyBase1: PolyBase,
        @Id(2) @Polymorphic val polyBase2: PolyBase
    )

    private val module: SerializersModule = BaseAndDerivedModule + SerializersModule {
        polymorphic(
            PolyDerived::class,
            PolyDerived.serializer()
        )
    }

    private val json = Json { useArrayPolymorphism = true; serializersModule = module }

    @Test
    fun testInheritanceJson() = parametrizedTest { jsonTestingMode ->
        val obj = Wrapper(
            PolyBase(2),
            PolyDerived("b")
        )
        val bytes = json.encodeToString(Wrapper.serializer(), obj, jsonTestingMode)
        assertEquals(
            """{"polyBase1":["kotlinx.serialization.PolyBase",{"id":2}],""" +
                    """"polyBase2":["kotlinx.serialization.PolyDerived",{"id":1,"s":"b"}]}""", bytes
        )
    }

    @Test
    fun testSerializeWithExplicitPolymorphicSerializer() = parametrizedTest { jsonTestingMode ->
        val obj = PolyDerived("b")
        val s = json.encodeToString(PolymorphicSerializer(PolyDerived::class), obj, jsonTestingMode)
        assertEquals("""["kotlinx.serialization.PolyDerived",{"id":1,"s":"b"}]""", s)
    }

    object PolyDefaultDeserializer : JsonTransformingSerializer(PolyDefault.serializer()) {
        override fun transformDeserialize(element: JsonElement): JsonElement = buildJsonObject {
            put("json", JsonObject(element.jsonObject.filterKeys { it != "type" }))
            put("id", 42)
        }
    }

    object EvenDefaultSerializer : SerializationStrategy {
        override val descriptor = buildClassSerialDescriptor("even") {
            element("parity")
        }

        override fun serialize(encoder: Encoder, value: PolyBase) {
            encoder.encodeStructure(descriptor) {
                encodeStringElement(descriptor, 0, "even")
            }
        }
    }

    object OddDefaultSerializer : SerializationStrategy {
        override val descriptor = buildClassSerialDescriptor("odd") {
            element("parity")
        }

        override fun serialize(encoder: Encoder, value: PolyBase) {
            encoder.encodeStructure(descriptor) {
                encodeStringElement(descriptor, 0, "odd")
            }
        }
    }

    @Test
    fun testDefaultDeserializer() = parametrizedTest { jsonTestingMode ->
        val withDefault = module + SerializersModule {
            polymorphicDefaultDeserializer(PolyBase::class) { name ->
                if (name == "foo") {
                    PolyDefaultDeserializer
                } else {
                    null
                }
            }
        }

        val adjustedJson = Json { serializersModule = withDefault }
        val string = """
            {"polyBase1":{"type":"kotlinx.serialization.PolyBase","id":239},
            "polyBase2":{"type":"foo","key":42}}""".trimIndent()
        val result = adjustedJson.decodeFromString(Wrapper.serializer(), string, jsonTestingMode)
        assertEquals(Wrapper(PolyBase(239), PolyDefault(JsonObject(mapOf("key" to JsonPrimitive(42))))), result)

        val replaced = string.replace("foo", "bar")
        assertFailsWithMessage("not found") { adjustedJson.decodeFromString(Wrapper.serializer(), replaced, jsonTestingMode) }
    }

    @Test
    fun testDefaultDeserializerForMissingDiscriminator() = parametrizedTest { jsonTestingMode ->
        val json = Json {
            serializersModule = module + SerializersModule {
                polymorphicDefaultDeserializer(PolyBase::class) { name ->
                    if (name == null) {
                        PolyDefaultDeserializer
                    } else {
                        null
                    }
                }
            }
        }
        val string = """
            {"polyBase1":{"type":"kotlinx.serialization.PolyBase","id":239},
            "polyBase2":{"key":42}}""".trimIndent()
        val result = json.decodeFromString(Wrapper.serializer(), string, jsonTestingMode)
        assertEquals(Wrapper(PolyBase(239), PolyDefault(JsonObject(mapOf("key" to JsonPrimitive(42))))), result)
    }

    @Test
    fun testDefaultSerializer() = parametrizedTest { jsonTestingMode ->
        val json = Json {
            serializersModule = module + SerializersModule {
                polymorphicDefaultSerializer(PolyBase::class) { value ->
                    if (value.id % 2 == 0) {
                        EvenDefaultSerializer
                    } else {
                        OddDefaultSerializer
                    }
                }
            }
        }
        val obj = Wrapper(
            PolyDefaultWithId(0),
            PolyDefaultWithId(1)
        )
        val s = json.encodeToString(Wrapper.serializer(), obj, jsonTestingMode)
        assertEquals("""{"polyBase1":{"type":"even","parity":"even"},"polyBase2":{"type":"odd","parity":"odd"}}""", s)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy