summaryrefslogtreecommitdiff
path: root/runtime/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt')
-rw-r--r--runtime/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt42
1 files changed, 42 insertions, 0 deletions
diff --git a/runtime/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt b/runtime/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt
new file mode 100644
index 00000000..12a1bdb5
--- /dev/null
+++ b/runtime/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.json.internal
+
+import kotlinx.serialization.*
+import kotlinx.serialization.json.*
+
+internal inline fun <T> JsonOutput.encodePolymorphically(serializer: SerializationStrategy<T>, value: T, ifPolymorphic: () -> Unit) {
+ if (serializer !is PolymorphicSerializer<*> || json.configuration.useArrayPolymorphism) {
+ serializer.serialize(this, value)
+ return
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ val actualSerializer = serializer.findPolymorphicSerializer(this, value as Any) as KSerializer<Any>
+ val kind = actualSerializer.descriptor.kind
+ checkKind(kind)
+
+ ifPolymorphic()
+ actualSerializer.serialize(this, value)
+}
+
+fun checkKind(kind: SerialKind) {
+ if (kind is UnionKind.ENUM_KIND) error("Enums cannot be serialized polymorphically with 'type' parameter. You can use 'JsonConfiguration.useArrayPolymorphism' instead")
+ if (kind is PrimitiveKind) error("Primitives cannot be serialized polymorphically with 'type' parameter. You can use 'JsonConfiguration.useArrayPolymorphism' instead")
+ if (kind is UnionKind.POLYMORPHIC) error("Actual serializer for polymorphic cannot be polymorphic itself")
+}
+
+internal fun <T> JsonInput.decodeSerializableValuePolymorphic(deserializer: DeserializationStrategy<T>): T {
+ if (deserializer !is PolymorphicSerializer<*> || json.configuration.useArrayPolymorphism) {
+ return deserializer.deserialize(this)
+ }
+
+ val jsonTree = cast<JsonObject>(decodeJson())
+ val type = jsonTree.getValue(json.configuration.classDiscriminator).content
+ (jsonTree.content as MutableMap).remove(json.configuration.classDiscriminator)
+ @Suppress("UNCHECKED_CAST")
+ val actualSerializer = deserializer.findPolymorphicSerializer(this, type) as KSerializer<T>
+ return json.readJson(jsonTree, actualSerializer)
+}