
commonMain.kotlinx.serialization.modules.PolymorphicModuleBuilder.kt Maven / Gradle / Ivy
/*
* Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.serialization.modules
import kotlinx.serialization.*
import kotlinx.serialization.internal.*
import kotlinx.serialization.json.*
import kotlin.reflect.*
/**
* A builder which registers all its content for polymorphic serialization in the scope of the [base class][baseClass].
* If [baseSerializer] is present, registers it as a serializer for [baseClass] (which will be used if base class is serializable).
* Subclasses and its serializers can be added with [subclass] builder function.
*
* To obtain an instance of this builder, use [SerializersModuleBuilder.polymorphic] DSL function.
*/
public class PolymorphicModuleBuilder internal constructor(
private val baseClass: KClass ,
private val baseSerializer: KSerializer ? = null
) {
private val subclasses: MutableList, KSerializer>> = mutableListOf()
private var defaultSerializerProvider: ((String) -> DeserializationStrategy?)? = null
/**
* Registers a [subclass] [serializer] in the resulting module under the [base class][Base].
*/
public fun subclass(subclass: KClass, serializer: KSerializer) {
subclasses.add(subclass to serializer)
}
/**
* Registers serializer provider that will be invoked if no polymorphic serializer is present.
* [defaultSerializerProvider] can be stateful and lookup a serializer for the missing type dynamically.
*
* Typically, if the class is not registered in advance, it is not possible to know the structure of the unknown
* type and have a precise serializer, so the default serializer has limited capabilities.
* To have a structural access to the unknown data, it is recommended to use [JsonTransformingSerializer]
* or [JsonContentPolymorphicSerializer] classes.
*/
public fun default(defaultSerializerProvider: (className: String) -> DeserializationStrategy?) {
require(this.defaultSerializerProvider == null) {
"Default serializer provider is already registered for class $baseClass: ${this.defaultSerializerProvider}"
}
this.defaultSerializerProvider = defaultSerializerProvider
}
@Suppress("UNCHECKED_CAST")
internal fun buildTo(builder: SerializersModuleBuilder) {
if (baseSerializer != null) builder.registerPolymorphicSerializer(baseClass, baseClass, baseSerializer)
subclasses.forEach { (kclass, serializer) ->
builder.registerPolymorphicSerializer(
baseClass,
kclass as KClass ,
serializer.cast()
)
}
if (defaultSerializerProvider != null) {
builder.registerDefaultPolymorphicSerializer(baseClass, defaultSerializerProvider!!, false)
}
}
@Deprecated(
message = "Use 'subclass' instead",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("subclass()")
)
public inline fun addSubclass(): Unit =
subclass(T::class, serializer())
@Deprecated(
message = "Use 'subclass(serializer)' instead",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("subclass(serializer)")
)
public inline fun addSubclass(serializer: KSerializer): Unit =
subclass(T::class, serializer)
@Deprecated(
message = "Use 'subclass(subclass, serializer)' instead",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("subclass(subclass, serializer)")
)
public fun addSubclass(subclass: KClass, serializer: KSerializer): Unit = subclass(subclass, serializer)
@Deprecated(
message = "This method was deprecated during serialization 1.0 API stabilization",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("subclass(serializer)")
)
public infix fun KClass.with(serializer: KSerializer): Unit {
subclass(this, serializer)
}
@Deprecated(
message = "This method was deprecated during serialization 1.0 API stabilization",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("subclass(serializer())")
)
public fun subclass(): Unit = TODO()
}
/**
* Registers a [subclass] [serializer] in the resulting module under the [base class][Base].
*/
public inline fun PolymorphicModuleBuilder .subclass(serializer: KSerializer): Unit =
subclass(T::class, serializer)
/**
* Registers a serializer for class [T] in the resulting module under the [base class][Base].
*/
public inline fun PolymorphicModuleBuilder .subclass(clazz: KClass): Unit =
subclass(clazz, serializer())
© 2015 - 2025 Weber Informatics LLC | Privacy Policy