
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 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 @PublishedApi internal constructor(
private val baseClass: KClass ,
private val baseSerializer: KSerializer ? = null
) {
private val subclasses: MutableList, KSerializer>> = mutableListOf()
private var defaultSerializerProvider: ((Base) -> SerializationStrategy ?)? = null
private var defaultDeserializerProvider: ((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)
}
/**
* Adds a default serializers provider associated with the given [baseClass] to the resulting module.
* [defaultDeserializerProvider] is invoked when no polymorphic serializers associated with the `className`
* were found. `className` could be `null` for formats that support nullable class discriminators
* (currently only `Json` with `JsonBuilder.useArrayPolymorphism` set to `false`)
*
* Default deserializers provider affects only deserialization process. To affect serialization process, use
* [SerializersModuleBuilder.polymorphicDefaultSerializer].
*
* [defaultDeserializerProvider] 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.
* If you're using `Json` format, you can get a structural access to the unknown data using `JsonContentPolymorphicSerializer`.
*
* @see SerializersModuleBuilder.polymorphicDefaultSerializer
*/
public fun defaultDeserializer(defaultDeserializerProvider: (className: String?) -> DeserializationStrategy ?) {
require(this.defaultDeserializerProvider == null) {
"Default deserializer provider is already registered for class $baseClass: ${this.defaultDeserializerProvider}"
}
this.defaultDeserializerProvider = defaultDeserializerProvider
}
/**
* Adds a default deserializers provider associated with the given [baseClass] to the resulting module.
* This function affect only deserialization process. To avoid confusion, it was deprecated and replaced with [defaultDeserializer].
* To affect serialization process, use [SerializersModuleBuilder.polymorphicDefaultSerializer].
*
* [defaultSerializerProvider] is invoked when no polymorphic serializers associated with the `className`
* were found. `className` could be `null` for formats that support nullable class discriminators
* (currently only `Json` with `JsonBuilder.useArrayPolymorphism` set to `false`)
*
* [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.
* If you're using `Json` format, you can get a structural access to the unknown data using `JsonContentPolymorphicSerializer`.
*
* @see defaultDeserializer
* @see SerializersModuleBuilder.polymorphicDefaultSerializer
*/
@Deprecated(
"Deprecated in favor of function with more precise name: defaultDeserializer",
ReplaceWith("defaultDeserializer(defaultSerializerProvider)"),
DeprecationLevel.WARNING // Since 1.5.0. Raise to ERROR in 1.6.0, hide in 1.7.0
)
public fun default(defaultSerializerProvider: (className: String?) -> DeserializationStrategy ?) {
defaultDeserializer(defaultSerializerProvider)
}
@Suppress("UNCHECKED_CAST")
@PublishedApi
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()
)
}
val defaultSerializer = defaultSerializerProvider
if (defaultSerializer != null) {
builder.registerDefaultPolymorphicSerializer(baseClass, defaultSerializer, false)
}
val defaultDeserializer = defaultDeserializerProvider
if (defaultDeserializer != null) {
builder.registerDefaultPolymorphicDeserializer(baseClass, defaultDeserializer, false)
}
}
}
/**
* 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