Docs Menu

Docs HomeDevelop ApplicationsMongoDB DriversKotlin Coroutine

Kotlin Serialization

On this page

  • Overview
  • Supported Types
  • Add Kotlin Serialization to Your Project
  • Annotate Data Classes
  • Custom Serializer Example
  • Customize the Serializer Configuration
  • Custom Codec Example

The Kotlin driver supports the kotlinx.serialization library for serializing and deserializing Kotlin objects.

The driver provides an efficient Bson serializer that you can use with classes marked as @Serializable to handle the serialization of Kotlin objects to BSON data.

You can also install the bson-kotlinx library to support custom codecs with configurations to encode defaults, encode nulls, and define class discriminators.

Note

To learn how to use the Codec interface instead of the Kotlin serialization library to specify custom encoding and decoding of Kotlin objects to BSON data, see the Codecs guide.

You might choose Kotlin serialization if you are already familiar with the framework or if you prefer to use an idiomatic Kotlin approach.

Although you can use the Kotlin driver with the Kotlin serialization Json library, the Json serializer does not directly support BSON value types such as ObjectId. You must provide a custom serializer that can handle the conversion between BSON and JSON.

The Kotlin driver supports:

  • All Kotlin types that are supported by the Kotlin serialization library

  • All available BSON types

Support for serialization in the Kotlin driver depends on the official Kotlin serialization library.

Select from the following tabs to see how to add the serialization dependencies to your project by using the Gradle and Maven package managers:

To declare a class as serializable, annotate your Kotlin data classes with the @Serializable annotation from the Kotlin serialization framework.

You can use your data classes in your code as normal after you mark them as serializable. The Kotlin driver and the Kotlin serialization framework handle the BSON serialization and deserialization.

This example shows a simple data class annotated with the following:

  • @Serializable to mark the class as serializable.

  • @SerialName to specify the name of the id and manufacturer properties in the BSON document. This can be used in place of the @BsonId and @BsonProperty annotations, which are unsupported in serializable classes.

  • @Contextual to mark the BSON id property to use the built-in ObjectIdSerializer. This annotation is required for BSON types to be serialized correctly.

@Serializable
data class PaintOrder(
@SerialName("_id") // Use instead of @BsonId
@Contextual val id: ObjectId?,
val color: String,
val qty: Int,
@SerialName("brand")
val manufacturer: String = "Acme" // Use instead of @BsonProperty
)

Note

You cannot use annotations from the org.bson.codecs.pojo.annotations package on @Serializable data classes.

For more information on serializable classes and available annotation classes, see the official Kotlin Serialization documentation.

You can create a custom serializer to handle how your data is represented in BSON. The Kotlin driver uses the KSerializer interface from the kotlinx.serialization package to implement custom serializers. You can specify the custom serializer as the parameter to the @Serializable annotation for a specific field.

The following example shows how to create a custom KSerializer instance to convert a kotlinx.datetime.Instant to a BsonDateTime:

object InstantAsBsonDateTime : KSerializer<Instant> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InstantAsBsonDateTime", PrimitiveKind.LONG)
override fun serialize(encoder: Encoder, value: Instant) {
when (encoder) {
is BsonEncoder -> encoder.encodeBsonValue(BsonDateTime(value.toEpochMilliseconds()))
else -> throw SerializationException("Instant is not supported by ${encoder::class}")
}
}
override fun deserialize(decoder: Decoder): Instant {
return when (decoder) {
is BsonDecoder -> Instant.fromEpochMilliseconds(decoder.decodeBsonValue().asDateTime().value)
else -> throw SerializationException("Instant is not supported by ${decoder::class}")
}
}
}

The following code shows the PaintOrder data class in which the orderDate field has an annotation that specifies the custom serializer class defined in the preceding code:

@Serializable
data class PaintOrder(
val color: String,
val qty: Int,
@Serializable(with = InstantAsBsonDateTime::class)
val orderDate: Instant,
)

For more information about the methods and classes mentioned in this section, see the following API documentation:

You can use the KotlinSerializerCodec class from the org.bson.codecs.kotlinx package to create a codec for your @Serializable data classes and customize what is stored.

Use the BsonConfiguration class to define the configuration, including whether to encode defaults, encode nulls, or define class discriminators.

To create a custom codec, install the bson-kotlinx dependency to your project. Select from the following tabs to see how to add the dependency to your project by using the Gradle and Maven package managers:

Note

bson-kotlin Dependency

You can also optionally install the bson-kotlin dependency through the default codec registry. This dependency uses reflection and the codec registry to support Kotlin data classes, but it does not support certain POJO annotations such as BsonDiscriminator, BsonExtraElements, and BsonConstructor. To learn more, see the bson-kotlin API documentation.

Generally, we recommend that you install and use the faster bson-kotlinx library for codec configuration.

Then, you can define your codec using the KotlinSerializerCodec.create() method and add it to the registry.

The following example shows how to create a codec using the KotlinSerializerCodec.create() method and configure it to not encode defaults:

import org.bson.codecs.configuration.CodecRegistries
import org.bson.codecs.kotlinx.BsonConfiguration
import org.bson.codecs.kotlinx.KotlinSerializerCodec
val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>(
bsonConfiguration = BsonConfiguration(encodeDefaults = false)
)
val registry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry
)

For more information about the methods and classes mentioned in this section, see the following API documentation:

←  DocumentsCodecs →