Package kotlinx.serialization

Basic core concepts and annotations that set up serialization process.

Basic core concepts and annotations that set up serialization process.

Types

BinaryFormat
Link copied to clipboard
common

SerialFormat that allows conversions to and from ByteArray via encodeToByteArray and decodeFromByteArray methods.

Not stable for inheritance

BinaryFormat interface is not stable for inheritance in 3rd party libraries, as new methods might be added to this interface or contracts of the existing methods can be changed.

It is safe to operate with instances of BinaryFormat and call its methods.

interface BinaryFormat : SerialFormat
Contextual
Link copied to clipboard
common

Instructs the plugin to use ContextualSerializer on a given property or type. Context serializer is usually used when serializer for type can only be found in runtime. It is also possible to apply ContextualSerializer to every property of the given type, using file-level UseContextualSerialization annotation.

@Target(allowedTargets = [AnnotationTarget.PROPERTY, AnnotationTarget.TYPE])
annotation class Contextual
ContextualSerializer
Link copied to clipboard
common

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.

class ContextualSerializer<T : Any>(serializableClass: KClass<T>, fallbackSerializer: KSerializer<T>?, typeArgumentsSerializers: Array<KSerializer<*>>) : KSerializer<T>
DeserializationStrategy
Link copied to clipboard
common

Deserialization strategy defines the serial form of a type T, including its structural description, declared by the descriptor and the actual deserialization process, defined by the implementation of the deserialize method.

deserialize method takes an instance of Decoder, and, knowing the serial form of the T, invokes primitive retrieval methods on the decoder and then transforms the received primitives to an instance of T.

A serial form of the type is a transformation of the concrete instance into a sequence of primitive values and vice versa. The serial form is not required to completely mimic the structure of the class, for example, a specific implementation may represent multiple integer values as a single string, omit or add some values that are present in the type, but not in the instance.

For a more detailed explanation of the serialization process, please refer to KSerializer documentation.

interface DeserializationStrategy<T>
EncodeDefault
Link copied to clipboard
common

Controls whether the target property is serialized when its value is equal to a default value, regardless of the format settings. Does not affect decoding and deserialization process.

Example of usage:

@Serializable
data class Foo(
@EncodeDefault(ALWAYS) val a: Int = 42,
@EncodeDefault(NEVER) val b: Int = 43,
val c: Int = 44
)

Json { encodeDefaults = false }.encodeToString((Foo()) // {"a": 42}
Json { encodeDefaults = true }.encodeToString((Foo()) // {"a": 42, "c":44}

@Target(allowedTargets = [AnnotationTarget.PROPERTY])
annotation class EncodeDefault(mode: EncodeDefault.Mode)
ExperimentalSerializationApi
Link copied to clipboard
common

Marks declarations that are still experimental in kotlinx.serialization, which means that the design of the corresponding declarations has open issues which may (or may not) lead to their changes in the future. Roughly speaking, there is a chance that those declarations will be deprecated in the near future or the semantics of their behavior may change in some way that may break some code.

By default, the following categories of API are experimental:

  • Writing 3rd-party serialization formats

  • Writing non-trivial custom serializers

  • Implementing SerialDescriptor interfaces

  • Not-yet-stable serialization formats that require additional polishing

@Target(allowedTargets = [AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS])
annotation class ExperimentalSerializationApi
InheritableSerialInfo
Link copied to clipboard
common

Meta-annotation that commands the compiler plugin to handle the annotation as serialization-specific. Serialization-specific annotations are preserved in the SerialDescriptor and can be retrieved during serialization process with SerialDescriptor.getElementAnnotations.

In contrary to regular SerialInfo, this one makes annotations inheritable: If class X marked as Serializable has any of its supertypes annotated with annotation A that has @InheritableSerialInfo on it, A appears in X's SerialDescriptor even if X itself is not annotated. It is possible to use A multiple times on different supertypes. Resulting X's SerialDescriptor.annotations would still contain only one instance of A. Note that if A has any arguments, their values should be the same across all hierarchy. Otherwise, a compilation error would be reported by the plugin.

Example:

@InheritableSerialInfo
annotation class A(val value: Int)

@A(1) // Annotation can also be inherited from interfaces
interface I

@Serializable
@A(1) // Argument value is the same as in I, no compiler error
abstract class Base: I

@Serializable
class Derived: Base()

// This function returns 1.
fun foo(): Int = Derived.serializer().descriptor.annotations.filterIsInstance<A>().single().value

@Target(allowedTargets = [AnnotationTarget.ANNOTATION_CLASS])
annotation class InheritableSerialInfo
InternalSerializationApi
Link copied to clipboard
common

Public API marked with this annotation is effectively internal, which means it should not be used outside of kotlinx.serialization. Signature, semantics, source and binary compatibilities are not guaranteed for this API and will be changed without any warnings or migration aids. If you cannot avoid using internal API to solve your problem, please report your use-case to serialization's issue tracker.

@Target(allowedTargets = [AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS])
annotation class InternalSerializationApi
KSerializer
Link copied to clipboard
common

KSerializer is responsible for the representation of a serial form of a type T in terms of encoders and decoders and for constructing and deconstructing T from/to a sequence of encoding primitives. For classes marked with @Serializable, can be obtained from generated companion extension .serializer() or from serializer<T>() function.

Serialization is decoupled from the encoding process to make it completely format-agnostic. Serialization represents a type as its serial form and is abstracted from the actual format (whether its JSON, ProtoBuf or a hashing) and unaware of the underlying storage (whether it is a string builder, byte array or a network socket), while encoding/decoding is abstracted from a particular type and its serial form and is responsible for transforming primitives ("here in an int property 'foo'" call from a serializer) into a particular format-specific representation ("for a given int, append a property name in quotation marks, then append a colon, then append an actual value" for JSON) and how to retrieve a primitive ("give me an int that is 'foo' property") from the underlying representation ("expect the next string to be 'foo', parse it, then parse colon, then parse a string until the next comma as an int and return it).

Serial form consists of a structural description, declared by the descriptor and actual serialization and deserialization processes, defined by the corresponding serialize and deserialize methods implementation.

Structural description specifies how the T is represented in the serial form: its kind (e.g. whether it is represented as a primitive, a list or a class), its elements and their positional names.

Serialization process is defined as a sequence of calls to an Encoder, and transforms a type T into a stream of format-agnostic primitives that represent T, such as "here is an int, here is a double and here is another nested object". It can be demonstrated by the example:

class MyData(int: Int, stringList: List<String>, alwaysZero: Long)

// .. serialize method of a corresponding serializer
fun serialize(encoder: Encoder, value: MyData): Unit = encoder.encodeStructure(descriptor) {
// encodeStructure encodes beginning and end of the structure
// encode 'int' property as Int
encodeIntElement(descriptor, index = 0, value.int)
// encode 'stringList' property as List<String>
encodeSerializableElement(descriptor, index = 1, serializer<List<String>>, value.stringList)
// don't encode 'alwaysZero' property because we decided to do so
} // end of the structure

Deserialization process is symmetric and uses Decoder.

interface KSerializer<T> : SerializationStrategy<T> , DeserializationStrategy<T>
Polymorphic
Link copied to clipboard
common

Instructs the serialization plugin to use PolymorphicSerializer on an annotated property or type usage. When used on class, replaces its serializer with PolymorphicSerializer everywhere.

This annotation is applied automatically to interfaces and serializable abstract classes and can be applied to open classes in addition to Serializable for the sake of simplicity.

Does not affect sealed classes, because they are gonna be serialized with subclasses automatically with special compiler plugin support which would be added later.

@Target(allowedTargets = [AnnotationTarget.PROPERTY, AnnotationTarget.TYPE, AnnotationTarget.CLASS])
annotation class Polymorphic
PolymorphicSerializer
Link copied to clipboard
common

This class provides support for multiplatform polymorphic serialization for interfaces and abstract classes.

To avoid the most common security pitfalls and reflective lookup (and potential load) of an arbitrary class, all serializable implementations of any polymorphic type must be registered in advance in the scope of base polymorphic type, efficiently preventing unbounded polymorphic serialization of an arbitrary type.

Polymorphic serialization is enabled automatically by default for interfaces and Serializable abstract classes. To enable this feature explicitly on other types, use @SerializableWith(PolymorphicSerializer::class) or Polymorphic annotation on the property.

Usage of the polymorphic serialization can be demonstrated by the following example:

abstract class BaseRequest()
@Serializable
data class RequestA(val id: Int): BaseRequest()
@Serializable
data class RequestB(val s: String): BaseRequest()

abstract class BaseResponse()
@Serializable
data class ResponseC(val payload: Long): BaseResponse()
@Serializable
data class ResponseD(val payload: ByteArray): BaseResponse()

@Serializable
data class Message(
@Polymorphic val request: BaseRequest,
@Polymorphic val response: BaseResponse
)

In this example, both request and response in Message are serializable with PolymorphicSerializer.

BaseRequest and BaseResponse are base classes and they are captured during compile time by the plugin. Yet PolymorphicSerializer for BaseRequest should only allow RequestA and RequestB serializers, and none of the response's serializers.

This is achieved via special registration function in the module:

val requestAndResponseModule = SerializersModule {
polymorphic(BaseRequest::class) {
subclass(RequestA::class)
subclass(RequestB::class)
}
polymorphic(BaseResponse::class) {
subclass(ResponseC::class)
subclass(ResponseD::class)
}
}

class PolymorphicSerializer<T : Any>(baseClass: KClass<T>) : AbstractPolymorphicSerializer<T>
Required
Link copied to clipboard
common

Indicates that property must be present during deserialization process, despite having a default value.

@Target(allowedTargets = [AnnotationTarget.PROPERTY])
annotation class Required
SealedClassSerializer
Link copied to clipboard
common

This class provides support for multiplatform polymorphic serialization of sealed classes.

In contrary to PolymorphicSerializer, all known subclasses with serializers must be passed in subclasses and subSerializers constructor parameters. If a subclass is a sealed class itself, all its subclasses are registered as well.

If a sealed hierarchy is marked with @Serializable, an instance of this class is provided automatically. In most of the cases, you won't need to perform any manual setup:

@Serializable
sealed class SimpleSealed {
@Serializable
public data class SubSealedA(val s: String) : SimpleSealed()

@Serializable
public data class SubSealedB(val i: Int) : SimpleSealed()
}

// will perform correct polymorphic serialization and deserialization:
Json.encodeToString(SimpleSealed.serializer(), SubSealedA("foo"))

However, it is possible to register additional subclasses using regular SerializersModule. It is required when one of the subclasses is an abstract class itself:

@Serializable
sealed class ProtocolWithAbstractClass {
@Serializable
abstract class Message : ProtocolWithAbstractClass() {
@Serializable
data class StringMessage(val description: String, val message: String) : Message()

@Serializable
data class IntMessage(val description: String, val message: Int) : Message()
}

@Serializable
data class ErrorMessage(val error: String) : ProtocolWithAbstractClass()
}

In this case, ErrorMessage would be registered automatically by the plugin, but StringMessage and IntMessage require manual registration, as described in PolymorphicSerializer documentation:

val abstractContext = SerializersModule {
polymorphic(ProtocolWithAbstractClass::class) {
subclass(ProtocolWithAbstractClass.Message.IntMessage::class)
subclass(ProtocolWithAbstractClass.Message.StringMessage::class)
// no need to register ProtocolWithAbstractClass.ErrorMessage
}
}

class SealedClassSerializer<T : Any>(serialName: String, baseClass: KClass<T>, subclasses: Array<KClass<out T>>, subclassSerializers: Array<KSerializer<out T>>) : AbstractPolymorphicSerializer<T>
SerialFormat
Link copied to clipboard
common

Represents an instance of a serialization format that can interact with KSerializer and is a supertype of all entry points for a serialization. It does not impose any restrictions on a serialized form or underlying storage, neither it exposes them.

Concrete data types and API for user-interaction are responsibility of a concrete subclass or subinterface, for example StringFormat, BinaryFormat or Json.

Typically, formats have their specific Encoder and Decoder implementations as private classes and do not expose them.

Not stable for inheritance

SerialFormat interface is not stable for inheritance in 3rd party libraries, as new methods might be added to this interface or contracts of the existing methods can be changed.

It is safe to operate with instances of SerialFormat and call its methods.

interface SerialFormat
SerialInfo
Link copied to clipboard
common

Meta-annotation that commands the compiler plugin to handle the annotation as serialization-specific. Serialization-specific annotations are preserved in the SerialDescriptor and can be retrieved during serialization process with SerialDescriptor.getElementAnnotations.

@Target(allowedTargets = [AnnotationTarget.ANNOTATION_CLASS])
annotation class SerialInfo
Serializable
Link copied to clipboard
common

The main entry point to the serialization process. Applying Serializable to the Kotlin class instructs the serialization plugin to automatically generate implementation of KSerializer for the current class, that can be used to serialize and deserialize the class. The generated serializer can be accessed with T.serializer() extension function on the class companion, both are generated by the plugin as well.

@Serializable
class MyData(val myData: AnotherData, val intProperty: Int, ...)

// Produces JSON string using the generated serializer
val jsonString = Json.encodeToJson(MyData.serializer(), instance)

Additionally, the user-defined serializer can be specified using with parameter:

@Serializable(with = MyAnotherDataCustomSerializer::class)
class MyAnotherData(...)

MyAnotherData.serializer() // <- returns MyAnotherDataCustomSerializer

For annotated properties, specifying with parameter is mandatory and can be used to override serializer on the use-site without affecting the rest of the usages:

@Serializable // By default is serialized as 3 byte components
class RgbPixel(val red: Short, val green: Short, val blue: Short)

@Serializable
class RgbExample(
@Serializable(with = RgbAsHexString::class) p1: RgpPixel, // Serialize as HEX string, e.g. #FFFF00
@Serializable(with = RgbAsSingleInt::class) p2: RgpPixel, // Serialize as single integer, e.g. 16711680
p3: RgpPixel // Serialize as 3 short components, e.g. { "red": 255, "green": 255, "blue": 0 }
)

In this example, each pixel will be serialized using different data representation.

For classes with generic type parameters, serializer() function requires one additional argument per each generic type parameter:

@Serializable
class Box<T>(value: T)

Box.serializer() // Doesn't compile
Box.serializer(Int.serializer()) // Returns serializer for Box<Int>
Box.serializer(Box.serializer(Int.serializer())) // Returns serializer for Box<Box<Int>>

Implementation details

In order to generate serializer function that is not a method on the particular instance, the class should have a companion object, either named or unnamed. Companion object is generated by the plugin if it is not declared, effectively exposing both companion and serializer() method to class ABI. If companion object already exists, only serializer method will be generated.

@Target(allowedTargets = [AnnotationTarget.PROPERTY, AnnotationTarget.CLASS, AnnotationTarget.TYPE])
annotation class Serializable(with: KClass<out KSerializer<*>>)
SerializationException
Link copied to clipboard
common

A generic exception indicating the problem in serialization or deserialization process. This is a generic exception type that can be thrown during the problem at any stage of the serialization, including encoding, decoding, serialization, deserialization. SerialFormat implementors should throw subclasses of this exception at any unexpected event, whether it is a malformed input or unsupported class layout.

open class SerializationException : IllegalArgumentException
SerializationStrategy
Link copied to clipboard
common

Serialization strategy defines the serial form of a type T, including its structural description, declared by the descriptor and the actual serialization process, defined by the implementation of the serialize method.

serialize method takes an instance of T and transforms it into its serial form (a sequence of primitives), calling the corresponding Encoder methods.

A serial form of the type is a transformation of the concrete instance into a sequence of primitive values and vice versa. The serial form is not required to completely mimic the structure of the class, for example, a specific implementation may represent multiple integer values as a single string, omit or add some values that are present in the type, but not in the instance.

For a more detailed explanation of the serialization process, please refer to KSerializer documentation.

interface SerializationStrategy<in T>
Serializer
Link copied to clipboard
common

Instructs the serialization plugin to turn this class into serializer for specified class forClass. However, it would not be used automatically. To apply it on particular class or property, use Serializable or UseSerializers, or Contextual with runtime registration.

@Serializer(forClass) is experimental and unstable feature that can be changed in future releases. Changes may include additional constraints on classes and objects marked with this annotation, behavioural changes and even serialized shape of the class.

@Target(allowedTargets = [AnnotationTarget.CLASS])
annotation class Serializer(forClass: KClass<*>)
SerialName
Link copied to clipboard
common

Overrides the name of a class or a property in the corresponding SerialDescriptor. Names and serial names are used by text-based serial formats in order to encode the name of the class or the name of the property, e.g. by Json.

By default, SerialDescriptor.serialName and SerialDescriptor.getElementName are associated with fully-qualified name of the target class and the name of the property respectively. Applying this annotation changes the visible name to the given value:

package foo

@Serializable // RegularName.serializer().descriptor.serialName is "foo.RegularName"
class RegularName(val myInt: Int)

@Serializable
@SerialName("CustomName") // Omit package from name that is used for diagnostic and polymorphism
class CustomName(@SerialName("int") val myInt: Int)

// Prints "{"myInt":42}"
println(Json.encodeToString(RegularName(42)))
// Prints "{"int":42}"
println(Json.encodeToString(CustomName(42)))

@Target(allowedTargets = [AnnotationTarget.PROPERTY, AnnotationTarget.CLASS])
annotation class SerialName(value: String)
StringFormat
Link copied to clipboard
common

SerialFormat that allows conversions to and from String via encodeToString and decodeFromString methods.

Not stable for inheritance

StringFormat interface is not stable for inheritance in 3rd party libraries, as new methods might be added to this interface or contracts of the existing methods can be changed.

It is safe to operate with instances of StringFormat and call its methods.

interface StringFormat : SerialFormat
Transient
Link copied to clipboard
common

Marks this property invisible for the whole serialization process, including serial descriptors. Transient properties should have default values.

@Target(allowedTargets = [AnnotationTarget.PROPERTY])
annotation class Transient
UseContextualSerialization
Link copied to clipboard
common

Instructs the plugin to use ContextualSerializer for every type in the current file that is listed in the forClasses.

@Target(allowedTargets = [AnnotationTarget.FILE])
annotation class UseContextualSerialization(forClasses: Array<out KClass<*>>)
UseSerializers
Link copied to clipboard
common

Adds serializerClasses to serializers resolving process inside the plugin. Each of serializerClasses must implement KSerializer.

Inside the file with this annotation, for each given property of type T in some serializable class, this list would be inspected for the presence of KSerializer<T>. If such serializer is present, it would be used instead of default.

Main use-case for this annotation is not to write @Serializable(with=SomeSerializer::class) on each property with custom serializer.

Serializers from this list have higher priority than default, but lesser priority than serializers defined on the property itself, such as Serializable (with=...) or Contextual.

@Target(allowedTargets = [AnnotationTarget.FILE])
annotation class UseSerializers(serializerClasses: Array<out KClass<out KSerializer<*>>>)

Functions

decodeFromByteArray
Link copied to clipboard
common

Decodes and deserializes the given byte array to the value of type T using deserializer retrieved from the reified type parameter.

inline fun <T> BinaryFormat.decodeFromByteArray(bytes: ByteArray): T
decodeFromHexString
Link copied to clipboard
common

Decodes byte array from the given hex string and the decodes and deserializes it to the value of type T, delegating it to the BinaryFormat.

This method is a counterpart to encodeToHexString

inline fun <T> BinaryFormat.decodeFromHexString(hex: String): T
fun <T> BinaryFormat.decodeFromHexString(deserializer: DeserializationStrategy<T>, hex: String): T
decodeFromString
Link copied to clipboard
common

Decodes and deserializes the given string to the value of type T using deserializer retrieved from the reified type parameter.

inline fun <T> StringFormat.decodeFromString(string: String): T
encodeToByteArray
Link copied to clipboard
common

Serializes and encodes the given value to byte array using serializer retrieved from the reified type parameter.

inline fun <T> BinaryFormat.encodeToByteArray(value: T): ByteArray
encodeToHexString
Link copied to clipboard
common

Serializes and encodes the given value to byte array, delegating it to the BinaryFormat, and then encodes resulting bytes to hex string.

Hex representation does not interfere with serialization and encoding process of the format and only applies transformation to the resulting array. It is recommended to use for debugging and testing purposes.

inline fun <T> BinaryFormat.encodeToHexString(value: T): String
fun <T> BinaryFormat.encodeToHexString(serializer: SerializationStrategy<T>, value: T): String
encodeToString
Link copied to clipboard
common

Serializes and encodes the given value to string using serializer retrieved from the reified type parameter.

inline fun <T> StringFormat.encodeToString(value: T): String
findPolymorphicSerializer
Link copied to clipboard
common
fun <T : Any> AbstractPolymorphicSerializer<T>.findPolymorphicSerializer(decoder: CompositeDecoder, klassName: String?): DeserializationStrategy<out T>
fun <T : Any> AbstractPolymorphicSerializer<T>.findPolymorphicSerializer(encoder: Encoder, value: T): SerializationStrategy<T>
serializer
Link copied to clipboard

Retrieves a serializer for the given type T. This method is a reified version of serializer(KType).

common
inline fun <T> serializer(): KSerializer<T>

Retrieves a KSerializer for the given KClass. The given class must be annotated with Serializable or be one of the built-in types.

This method uses platform-specific reflection available for the given erased KClass and is not recommended to use this method for anything, but last-ditch resort, e.g. when all type info is lost, your application has crashed and it is the final attempt to log or send some serializable data.

The recommended way to retrieve the serializer is inline serializer function and serializer(KType)

This API is not guaranteed to work consistent across different platforms or to work in cases that slightly differ from "plain @Serializable class" and have platform and reflection specific limitations.

Constraints

This paragraph explains known (but not all!) constraints of the serializer() implementation. Please note that they are not bugs, but implementation restrictions that we cannot workaround.

  • This method may behave differently on JVM, JS and Native because of runtime reflection differences

  • Serializers for classes with generic parameters are ignored by this method

  • External serializers generated with Serializer(forClass = ) are not lookuped consistently

  • Serializers for classes with named companion objects are not lookuped consistently

common
fun <T : Any> KClass<T>.serializer(): KSerializer<T>

Retrieves serializer for the given type T from the current SerializersModule and, if not found, fallbacks to plain serializer method.

common
inline fun <T> SerializersModule.serializer(): KSerializer<T>

Reflectively constructs a serializer for the given reflective Java type. serializer is intended to be used as an interoperability layer for libraries like GSON and Retrofit, that operate with reflective Java Type and cannot use typeOf.

For application-level serialization, it is recommended to use serializer<T>() instead as it is aware of Kotlin-specific type information, such as nullability, sealed classes and object singletons.

fun serializer(type: Type): KSerializer<Any>

Creates a serializer for the given type. type argument can be obtained with experimental typeOf method.

common
fun serializer(type: KType): KSerializer<Any?>

Retrieves serializer for the given reflective Java type using reflective construction and contextual lookup for non-serializable types.

serializer is intended to be used as an interoperability layer for libraries like GSON and Retrofit, that operate with reflective Java Type and cannot use typeOf.

For application-level serialization, it is recommended to use serializer<T>() instead as it is aware of Kotlin-specific type information, such as nullability, sealed classes and object singletons.

fun SerializersModule.serializer(type: Type): KSerializer<Any>

Attempts to create a serializer for the given type and fallbacks to contextual lookup for non-serializable types. type argument can be obtained with experimental typeOf method.

common
fun SerializersModule.serializer(type: KType): KSerializer<Any?>
serializerOrNull
Link copied to clipboard

Retrieves a KSerializer for the given KClass or returns null if none is found. The given class must be annotated with Serializable or be one of the built-in types. This method uses platform-specific reflection available for the given erased KClass and it is not recommended to use this method for anything, but last-ditch resort, e.g. when all type info is lost, your application has crashed and it is the final attempt to log or send some serializable data.

This API is not guaranteed to work consistent across different platforms or to work in cases that slightly differ from "plain @Serializable class".

Constraints

This paragraph explains known (but not all!) constraints of the serializer() implementation. Please note that they are not bugs, but implementation restrictions that we cannot workaround.

  • This method may behave differently on JVM, JS and Native because of runtime reflection differences

  • Serializers for classes with generic parameters are ignored by this method

  • External serializers generated with Serializer(forClass = ) are not lookuped consistently

  • Serializers for classes with named companion objects are not lookuped consistently

common
fun <T : Any> KClass<T>.serializerOrNull(): KSerializer<T>?

Reflectively constructs a serializer for the given reflective Java type. serializer is intended to be used as an interoperability layer for libraries like GSON and Retrofit, that operate with reflective Java Type and cannot use typeOf.

For application-level serialization, it is recommended to use serializer<T>() instead as it is aware of Kotlin-specific type information, such as nullability, sealed classes and object singletons.

Returns null if serializer cannot be created (provided type or its type argument is not serializable).

fun serializerOrNull(type: Type): KSerializer<Any>?

Creates a serializer for the given type. type argument can be obtained with experimental typeOf method. Returns null if serializer cannot be created (provided type or its type argument is not serializable).

common
fun serializerOrNull(type: KType): KSerializer<Any?>?

Retrieves serializer for the given reflective Java type using reflective construction and contextual lookup for non-serializable types.

serializer is intended to be used as an interoperability layer for libraries like GSON and Retrofit, that operate with reflective Java Type and cannot use typeOf.

For application-level serialization, it is recommended to use serializer<T>() instead as it is aware of Kotlin-specific type information, such as nullability, sealed classes and object singletons.

Returns null if serializer cannot be created (provided type or its type argument is not serializable).

fun SerializersModule.serializerOrNull(type: Type): KSerializer<Any>?

Attempts to create a serializer for the given type and fallbacks to contextual lookup for non-serializable types. type argument can be obtained with experimental typeOf method. Returns null if serializer cannot be created (provided type or its type argument is not serializable and is not registered in this module).

common
fun SerializersModule.serializerOrNull(type: KType): KSerializer<Any?>?