diff options
author | Sergey Shanshin <sergey.shanshin@jetbrains.com> | 2022-06-30 15:43:42 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-30 15:43:42 +0300 |
commit | 5e8ccad1f70a9457e0ffe6ae6b10a0bd0eaaa618 (patch) | |
tree | e522ba5e8da0cb4701f4a259d9f2ba5b43b42bf2 /formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic | |
parent | 605a35faa87534e24482aa00a52a2a71bebd51a3 (diff) | |
download | kotlinx.serialization-5e8ccad1f70a9457e0ffe6ae6b10a0bd0eaaa618.tar.gz |
Add Okio integration (#1901)
* Add okio integration as separate module json-okio
* Extract separate module json-tests that tests both Java streams and okio
* Rewrite Java stream writer so that it uses much faster in-place UTF8 encoder instead of java.io.Writer
* Add benchmarks for streams and okio
* Disable targets for tests that are not supported by okio (they can't be run on LinuxX64-86 hosts anyway)
Diffstat (limited to 'formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic')
12 files changed, 713 insertions, 0 deletions
diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt new file mode 100644 index 00000000..d58e26b6 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlin.test.* + +class JsonContentPolymorphicSerializerTest : JsonTestBase() { + val json = Json + + @Serializable + sealed class Choices { + @Serializable + data class HasA(val a: String) : Choices() + + @Serializable + data class HasB(val b: Int) : Choices() + + @Serializable + data class HasC(val c: Boolean) : Choices() + } + + object ChoicesParametricSerializer : JsonContentPolymorphicSerializer<Choices>(Choices::class) { + override fun selectDeserializer(element: JsonElement): KSerializer<out Choices> { + val obj = element.jsonObject + return when { + "a" in obj -> Choices.HasA.serializer() + "b" in obj -> Choices.HasB.serializer() + "c" in obj -> Choices.HasC.serializer() + else -> throw SerializationException("Unknown choice") + } + } + } + + @Serializable + data class WithChoices(@Serializable(ChoicesParametricSerializer::class) val response: Choices) + + private val testDataInput = listOf( + """{"response":{"a":"string"}}""", + """{"response":{"b":42}}""", + """{"response":{"c":true}}""" + ) + + private val testDataOutput = listOf( + WithChoices(Choices.HasA("string")), + WithChoices(Choices.HasB(42)), + WithChoices(Choices.HasC(true)) + ) + + @Test + fun testParsesParametrically() = parametrizedTest { streaming -> + for (i in testDataInput.indices) { + assertEquals( + testDataOutput[i], + json.decodeFromString(WithChoices.serializer(), testDataInput[i], streaming), + "failed test on ${testDataInput[i]}, jsonTestingMode = $streaming" + ) + } + } + + @Test + fun testSerializesParametrically() = parametrizedTest { streaming -> + for (i in testDataOutput.indices) { + assertEquals( + testDataInput[i], + json.encodeToString(WithChoices.serializer(), testDataOutput[i], streaming), + "failed test on ${testDataOutput[i]}, jsonTestingMode = $streaming" + ) + } + } + + interface Payment { + val amount: String + } + + @Serializable + data class SuccessfulPayment(override val amount: String, val date: String) : Payment + + @Serializable + data class RefundedPayment(override val amount: String, val date: String, val reason: String) : Payment + + object PaymentSerializer : JsonContentPolymorphicSerializer<Payment>(Payment::class) { + override fun selectDeserializer(element: JsonElement) = when { + "reason" in element.jsonObject -> RefundedPayment.serializer() + else -> SuccessfulPayment.serializer() + } + } + + @Test + fun testDocumentationSample() = parametrizedTest { streaming -> + assertEquals( + SuccessfulPayment("1.0", "03.02.2020"), + json.decodeFromString(PaymentSerializer, """{"amount":"1.0","date":"03.02.2020"}""", streaming) + ) + assertEquals( + RefundedPayment("2.0", "03.02.2020", "complaint"), + json.decodeFromString(PaymentSerializer, """{"amount":"2.0","date":"03.02.2020","reason":"complaint"}""", streaming) + ) + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt new file mode 100644 index 00000000..f0229046 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.* +import kotlin.test.* + +class JsonDeserializePolymorphicTwiceTest { + + @Serializable + sealed class Foo { + @Serializable + data class Bar(val a: Int) : Foo() + } + + @Test + fun testDeserializeTwice() { // #812 + val json = Json.encodeToJsonElement(Foo.serializer(), Foo.Bar(1)) + assertEquals(Foo.Bar(1), Json.decodeFromJsonElement(Foo.serializer(), json)) + assertEquals(Foo.Bar(1), Json.decodeFromJsonElement(Foo.serializer(), json)) + } +}
\ No newline at end of file diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt new file mode 100644 index 00000000..5722e8df --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.Polymorphic +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonTestBase +import kotlin.test.Test +import kotlin.test.assertFails + +class JsonListPolymorphismTest : JsonTestBase() { + + @Serializable + internal data class ListWrapper(val list: List<@Polymorphic InnerBase>) + + @Test + fun testPolymorphicValues() = assertJsonFormAndRestored( + ListWrapper.serializer(), + ListWrapper(listOf(InnerImpl(1), InnerImpl2(2))), + """{"list":[""" + + """{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":1,"str":"default","nullable":null},""" + + """{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":2}]}""", + polymorphicRelaxedJson) + + @Serializable + internal data class ListNullableWrapper(val list: List<@Polymorphic InnerBase?>) + + @Test + fun testPolymorphicNullableValues() = assertJsonFormAndRestored( + ListNullableWrapper.serializer(), + ListNullableWrapper(listOf(InnerImpl(1), null)), + """{"list":[""" + + """{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":1,"str":"default","nullable":null},""" + + "null]}", + polymorphicRelaxedJson) + + @Test + fun testPolymorphicNullableValuesWithNonNullSerializerFails() = + parametrizedTest { jsonTestingMode -> + val wrapper = ListNullableWrapper(listOf(InnerImpl(1), null)) + val serialized = polymorphicRelaxedJson.encodeToString(ListNullableWrapper.serializer(), wrapper, jsonTestingMode) + assertFails { polymorphicRelaxedJson.decodeFromString(ListWrapper.serializer(), serialized, jsonTestingMode) } + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt new file mode 100644 index 00000000..b2adaa71 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlin.test.* + +class JsonMapPolymorphismTest : JsonTestBase() { + + @Serializable + internal data class MapWrapper(val map: Map<String, @Polymorphic InnerBase>) + + @Test + fun testPolymorphicValues() = assertJsonFormAndRestored( + MapWrapper.serializer(), + MapWrapper(mapOf("k1" to InnerImpl(1), "k2" to InnerImpl2(2))), + """{"map":{"k1":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":1,"str":"default","nullable":null},"k2":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":2}}}""".trimMargin(), + polymorphicJson + ) + + @Serializable + internal data class MapNullableWrapper(val map: Map<String, @Polymorphic InnerBase?>) + + @Serializable + internal data class MapKeys(val map: Map<@Polymorphic InnerBase, String>) + + @Test + fun testPolymorphicNullableValues() = assertJsonFormAndRestored( + MapNullableWrapper.serializer(), + MapNullableWrapper(mapOf("k1" to InnerImpl(1), "k2" to null)), + """{"map":{"k1":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":1,"str":"default","nullable":null},"k2":null}}""", + polymorphicJson + ) + + @Test + fun testPolymorphicKeys() { + val json = Json { + allowStructuredMapKeys = true + serializersModule = polymorphicTestModule + encodeDefaults = true + } + assertJsonFormAndRestored( + MapKeys.serializer(), + MapKeys(mapOf(InnerImpl(1) to "k2", InnerImpl2(2) to "k2")), + """{"map":[{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":1,"str":"default","nullable":null},"k2",{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":2},"k2"]}""", + json + ) + } + + @Test + fun testPolymorphicKeysInArray() { + val json = Json { + allowStructuredMapKeys = true + useArrayPolymorphism = true + serializersModule = polymorphicTestModule + encodeDefaults = true + } + assertJsonFormAndRestored( + MapKeys.serializer(), + MapKeys(mapOf(InnerImpl(1) to "k2", InnerImpl2(2) to "k2")), + """{"map":[["kotlinx.serialization.json.polymorphic.InnerImpl",{"field":1,"str":"default","nullable":null}],"k2",["kotlinx.serialization.json.polymorphic.InnerImpl2",{"field":2}],"k2"]}""", + json + ) + } + + @Serializable + abstract class Base + + @Serializable + data class Derived(val myMap: Map<StringData, String>) : Base() + + @Test + fun testIssue480() { + val json = Json { + allowStructuredMapKeys = true + serializersModule = SerializersModule { + polymorphic(Base::class) { + subclass(Derived.serializer()) + } + } + } + + assertJsonFormAndRestored( + Base.serializer(), + Derived(mapOf(StringData("hi") to "hello")), + """{"type":"kotlinx.serialization.json.polymorphic.JsonMapPolymorphismTest.Derived","myMap":[{"data":"hi"},"hello"]}""", + json + ) + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt new file mode 100644 index 00000000..0caa99dd --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlin.test.* + +class JsonNestedPolymorphismTest : JsonTestBase() { + + private val polymorphicJson = Json { + isLenient = true + encodeDefaults = true + serializersModule = SerializersModule { + polymorphic(Any::class) { + subclass(InnerImpl.serializer()) + subclass(InnerImpl2.serializer()) + subclass(OuterImpl.serializer()) + + } + + polymorphic(InnerBase::class) { + subclass(InnerImpl.serializer()) + subclass(InnerImpl2.serializer()) + } + } + } + + @Serializable + internal data class NestedGenericsList(val list: List<List<@Polymorphic Any>>) + + @Test + fun testAnyList() = assertJsonFormAndRestored( + NestedGenericsList.serializer(), + NestedGenericsList(listOf(listOf(InnerImpl(1)), listOf(InnerImpl(2)))), + """{"list":[[""" + + """{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":1,"str":"default","nullable":null}],[""" + + """{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":2,"str":"default","nullable":null}]]}""", + polymorphicJson) + + @Serializable + internal data class NestedGenericsMap(val list: Map<String, Map<String, @Polymorphic Any>>) + + @Test + fun testAnyMap() = assertJsonFormAndRestored( + NestedGenericsMap.serializer(), + NestedGenericsMap(mapOf("k1" to mapOf("k1" to InnerImpl(1)))), + """{"list":{"k1":{"k1":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl",""" + + """"field":1,"str":"default","nullable":null}}}}""", + polymorphicJson) + + @Serializable + internal data class AnyWrapper(@Polymorphic val any: Any) + + @Test + fun testAny() = assertJsonFormAndRestored( + AnyWrapper.serializer(), + AnyWrapper(OuterImpl(InnerImpl2(1), InnerImpl(2))), + """{"any":""" + + """{"type":"kotlinx.serialization.json.polymorphic.OuterImpl",""" + + """"base":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":1},""" + + """"base2":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":2,"str":"default","nullable":null}}}""", + polymorphicJson) +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt new file mode 100644 index 00000000..ba8d0dfe --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlin.test.* + +class JsonNullablePolymorphicTest : JsonTestBase() { + @Serializable + data class NullableHolder(@Polymorphic val a: Any?) + + @Serializable + @SerialName("Box") + data class Box(val i: Int) + + @Test + fun testPolymorphicNulls() { + val json = Json { + serializersModule = SerializersModule { + polymorphic(Any::class) { + subclass(Box::class) + } + } + } + + assertJsonFormAndRestored(serializer(), NullableHolder(Box(42)), """{"a":{"type":"Box","i":42}}""", json) + assertJsonFormAndRestored(serializer(), NullableHolder(null), """{"a":null}""", json) + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt new file mode 100644 index 00000000..b11e9dad --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.json.* +import kotlin.test.* + +class JsonPolymorphicClassDescriptorTest : JsonTestBase() { + + private val json = Json { + classDiscriminator = "class" + serializersModule = polymorphicTestModule + encodeDefaults = true + } + + @Test + fun testPolymorphicProperties() = assertJsonFormAndRestored( + InnerBox.serializer(), + InnerBox(InnerImpl(42, "foo")), + """{"base":{"class":"kotlinx.serialization.json.polymorphic.InnerImpl",""" + + """"field":42,"str":"foo","nullable":null}}""", + json + ) +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt new file mode 100644 index 00000000..e47f5790 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlin.test.* + +class JsonPolymorphicObjectTest : JsonTestBase() { + + @Serializable + data class Holder(@Polymorphic val a: Any) + + @Serializable + @SerialName("MyObject") + object MyObject { + @Suppress("unused") + val unused = 42 + } + + val json = Json { + serializersModule = SerializersModule { + polymorphic(Any::class) { + subclass(MyObject::class, MyObject.serializer()) // JS bug workaround + } + } + } + + @Test + fun testRegularPolymorphism() { + assertJsonFormAndRestored(Holder.serializer(), Holder(MyObject), """{"a":{"type":"MyObject"}}""", json) + } + + @Test + fun testArrayPolymorphism() { + val json = Json(from = json) { + useArrayPolymorphism = true + } + assertJsonFormAndRestored(Holder.serializer(), Holder(MyObject), """{"a":["MyObject",{}]}""", json) + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt new file mode 100644 index 00000000..b7d4f122 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.json.internal.* +import kotlinx.serialization.modules.* +import kotlinx.serialization.test.assertFailsWithSerial +import kotlin.test.* + +class JsonPolymorphismExceptionTest : JsonTestBase() { + + @Serializable + abstract class Base + + @Serializable + @SerialName("derived") + class Derived(val nested: Nested = Nested()) : Base() + + @Serializable + class Nested + + @Test + fun testDecodingException() = parametrizedTest { jsonTestingMode -> + val serialModule = SerializersModule { + polymorphic(Base::class) { + subclass(Derived::class) + } + } + + assertFailsWithSerial("JsonDecodingException") { + Json { serializersModule = serialModule }.decodeFromString(Base.serializer(), """{"type":"derived","nested":null}""", jsonTestingMode) + } + } + + @Test + fun testMissingDiscriminator() = parametrizedTest { jsonTestingMode -> + val serialModule = SerializersModule { + polymorphic(Base::class) { + subclass(Derived::class) + } + } + + assertFailsWithSerial("JsonDecodingException") { + Json { serializersModule = serialModule }.decodeFromString(Base.serializer(), """{"nested":{}}""", jsonTestingMode) + } + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt new file mode 100644 index 00000000..7a825395 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlin.test.* + +class JsonProhibitedPolymorphicKindsTest : JsonTestBase() { + + @Serializable + sealed class Base { + @Serializable + class Impl(val data: Int) : Base() + } + + @Serializable + enum class MyEnum + + @Test + fun testSealedSubclass() { + assertFailsWith<IllegalArgumentException> { + Json(true) { + subclass(Base::class) + } + } + assertFailsWith<IllegalArgumentException> { + Json(false) { + subclass(Base::class) + } + } + } + + @Test + fun testPrimitive() { + assertFailsWith<IllegalArgumentException> { + Json(false) { + subclass(Int::class) + } + } + + // Doesn't fail + Json(true) { + subclass(Int::class) + } + } + + @Test + fun testEnum() { + assertFailsWith<IllegalArgumentException> { + Json(false) { + subclass(MyEnum::class) + } + } + + Json(true) { + subclass(MyEnum::class) + } + } + + @Test + fun testStructures() { + assertFailsWith<IllegalArgumentException> { + Json(false) { + subclass(serializer<Map<Int, Int>>()) + } + } + + assertFailsWith<IllegalArgumentException> { + Json(false) { + subclass(serializer<List<Int>>()) + } + } + + Json(true) { + subclass(serializer<List<Int>>()) + } + + + Json(true) { + subclass(serializer<Map<Int, Int>>()) + } + } + + private fun Json(useArrayPolymorphism: Boolean, builderAction: PolymorphicModuleBuilder<Any>.() -> Unit) = Json { + this.useArrayPolymorphism = useArrayPolymorphism + serializersModule = SerializersModule { + polymorphic(Any::class) { + builderAction() + } + } + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt new file mode 100644 index 00000000..e2e10e24 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.PolymorphicSerializer +import kotlinx.serialization.json.JsonTestBase +import kotlin.test.Test +import kotlin.test.assertEquals + +class JsonPropertyPolymorphicTest : JsonTestBase() { + + @Test + fun testPolymorphicProperties() = assertJsonFormAndRestored( + InnerBox.serializer(), + InnerBox(InnerImpl(42, "foo")), + """{"base":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl",""" + + """"field":42,"str":"foo","nullable":null}}""", + polymorphicRelaxedJson) + + @Test + fun testFlatPolymorphic() = parametrizedTest { jsonTestingMode -> + val base: InnerBase = InnerImpl(42, "foo") + val string = polymorphicRelaxedJson.encodeToString(PolymorphicSerializer(InnerBase::class), base, jsonTestingMode) + assertEquals("""{"type":"kotlinx.serialization.json.polymorphic.InnerImpl",""" + + """"field":42,"str":"foo","nullable":null}""", string) + assertEquals(base, polymorphicRelaxedJson.decodeFromString(PolymorphicSerializer(InnerBase::class), string, jsonTestingMode)) + } + + @Test + fun testNestedPolymorphicProperties() = assertJsonFormAndRestored( + OuterBox.serializer(), + OuterBox(OuterImpl(InnerImpl(42), InnerImpl2(42)), InnerImpl2(239)), + """{"outerBase":{""" + + """"type":"kotlinx.serialization.json.polymorphic.OuterImpl",""" + + """"base":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":42,"str":"default","nullable":null},""" + + """"base2":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":42}},""" + + """"innerBase":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":239}}""", + polymorphicRelaxedJson) + + @Test + fun testPolymorphicNullableProperties() = assertJsonFormAndRestored( + InnerNullableBox.serializer(), + InnerNullableBox(InnerImpl(42, "foo")), + """{"base":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl",""" + + """"field":42,"str":"foo","nullable":null}}""", + polymorphicRelaxedJson) + + @Test + fun testPolymorphicNullablePropertiesWithNull() = + assertJsonFormAndRestored(InnerNullableBox.serializer(), InnerNullableBox(null), """{"base":null}""", polymorphicJson) + + @Test + fun testNestedPolymorphicNullableProperties() = assertJsonFormAndRestored( + OuterNullableBox.serializer(), + OuterNullableBox(OuterNullableImpl(InnerImpl(42), null), InnerImpl2(239)), + """{"outerBase":{""" + + """"type":"kotlinx.serialization.json.polymorphic.OuterNullableImpl",""" + + """"base":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl","field":42,"str":"default","nullable":null},"base2":null},""" + + """"innerBase":{"type":"kotlinx.serialization.json.polymorphic.InnerImpl2","field":239}}""", + polymorphicRelaxedJson) +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt new file mode 100644 index 00000000..e46de17a --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.polymorphic + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlin.native.concurrent.* + +@Serializable +internal open class InnerBase + +internal interface OuterBase + +@Serializable +internal data class InnerImpl(val field: Int, val str: String = "default", val nullable: Int? = null) : InnerBase() + +@Serializable +internal data class InnerImpl2(val field: Int) : InnerBase() + +@Serializable +internal data class InnerBox(@Polymorphic val base: InnerBase) + +@Serializable +internal data class InnerNullableBox(@Polymorphic val base: InnerBase?) + +@Serializable +internal data class OuterImpl(@Polymorphic val base: InnerBase, @Polymorphic val base2: InnerBase) : OuterBase + +@Serializable +internal data class OuterNullableImpl(@Polymorphic val base: InnerBase?, @Polymorphic val base2: InnerBase?) : OuterBase + +@Serializable +internal data class OuterBox(@Polymorphic val outerBase: OuterBase, @Polymorphic val innerBase: InnerBase) + +@Serializable +internal data class OuterNullableBox(@Polymorphic val outerBase: OuterBase?, @Polymorphic val innerBase: InnerBase?) + +@SharedImmutable +internal val polymorphicTestModule = SerializersModule { + polymorphic(InnerBase::class) { + subclass(InnerImpl.serializer()) + subclass(InnerImpl2.serializer()) + } + + polymorphic(OuterBase::class) { + subclass(OuterImpl.serializer()) + subclass(OuterNullableImpl.serializer()) + } +} + +@SharedImmutable +internal val polymorphicJson = Json { + serializersModule = polymorphicTestModule + encodeDefaults = true +} + +@SharedImmutable +internal val polymorphicRelaxedJson = Json { + isLenient = true + serializersModule = polymorphicTestModule + encodeDefaults = true +} |