-
Notifications
You must be signed in to change notification settings - Fork 626
/
ContextualSerializer.kt
64 lines (56 loc) · 2.87 KB
/
ContextualSerializer.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.serialization
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.internal.*
import kotlinx.serialization.modules.*
import kotlin.reflect.*
/**
* This class provides support for retrieving a serializer in runtime, instead of using the one precompiled by the serialization plugin.
* This serializer is enabled by [Contextual] or [UseContextualSerialization].
*
* Typical usage of `ContextualSerializer` would be a serialization of a class which does not have
* static serializer (e.g. Java class or class from 3rd party library);
* or desire to override serialized class form in one dedicated output format.
*
* Serializers are being looked for in a [SerializersModule] from the target [Encoder] or [Decoder], using statically known [KClass].
* To create a serial module, use [SerializersModule] factory function.
* To pass it to encoder and decoder, refer to particular [SerialFormat]'s documentation.
*
* Usage of contextual serializer can be demonstrated by the following example:
* ```
* import java.util.Date
*
* @Serializable
* class ClassWithDate(val data: String, @Contextual val timestamp: Date)
*
* val moduleForDate = serializersModule(MyISO8601DateSerializer)
* val json = Json { serializersModule = moduleForDate }
* json.encodeToString(ClassWithDate("foo", Date())
* ```
*
* If type of the property marked with `@Contextual` is `@Serializable` by itself, the plugin-generated serializer is
* used as a fallback if no serializers associated with a given type is registered in the module.
* The fallback serializer is determined by the static type of the property, not by its actual type.
*/
@ExperimentalSerializationApi
public class ContextualSerializer<T : Any>(
private val serializableClass: KClass<T>,
private val fallbackSerializer: KSerializer<T>?,
private val typeParametersSerializers: Array<KSerializer<*>>
) : KSerializer<T> {
private fun serializer(serializersModule: SerializersModule): KSerializer<T> =
serializersModule.getContextual(serializableClass) ?: fallbackSerializer ?: serializableClass.serializerNotRegistered()
// Used from auto-generated code
public constructor(serializableClass: KClass<T>) : this(serializableClass, null, EMPTY_SERIALIZER_ARRAY)
public override val descriptor: SerialDescriptor =
buildSerialDescriptor("kotlinx.serialization.ContextualSerializer", SerialKind.CONTEXTUAL).withContext(serializableClass)
public override fun serialize(encoder: Encoder, value: T) {
encoder.encodeSerializableValue(serializer(encoder.serializersModule), value)
}
public override fun deserialize(decoder: Decoder): T {
return decoder.decodeSerializableValue(serializer(decoder.serializersModule))
}
}