Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions snooty.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ api = "https://mongodb.github.io/mongo-java-driver/{+version-number+}/apidocs/mo
java-api = "https://mongodb.github.io/mongo-java-driver/{+version-number+}"
core-api = "{+java-api+}/apidocs/mongodb-driver-core"
kotlin-docs = "https://kotlinlang.org"
serialization-version = "1.5.1"
9 changes: 8 additions & 1 deletion source/data-formats.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Specialized Data Formats
:titlesonly:
:maxdepth: 1

/data-formats/serialization
/data-formats/bson
/data-formats/time-series

Expand All @@ -30,7 +31,13 @@ Specialized Data Formats
Overview
--------

You can use several types of specialized document data formats in your {+driver-short+}
The {+driver-short+} supports the ``kotlinx.serialization`` library for
serializing and deserializing {+language+} objects. You can use this
library to convert between MongoDB documents and different data formats
in your application. To learn more about serialization, see the
:ref:`kotlin-sync-serialization` guide.

You can use several types of specialized document data formats in your
application. To learn how to work with these data formats, see the following
sections:

Expand Down
299 changes: 299 additions & 0 deletions source/data-formats/serialization.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
.. _kotlin-sync-serialization:

====================
Kotlin Serialization
====================

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: code example, data model, conversion, polymorphism

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

Overview
--------

You can use the ``kotlinx.serialization`` library when
serializing and deserializing {+language+} objects in your application.

The driver provides an efficient ``Bson`` serializer that you can use with
classes marked with the ``@Serializable`` annotation to handle the
serialization of {+language+} objects to BSON data.

Although you can use the {+language+} 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.

We recommend installing the ``bson-kotlinx`` library to support
custom codecs that have configurations to encode defaults, nulls, and
define class discriminators.

.. TODO .. note::
.. To learn how to use the ``Codec`` interface instead of the
.. ``kotlinx.serialization`` library to specify custom
.. serialization behavior, see the :ref:`kotlin-sync-codecs` guide.
..
.. You might choose to use {+language+} serialization if you
.. are already familiar with the framework or if you prefer
.. to use an idiomatic approach.

Supported Types
~~~~~~~~~~~~~~~

The {+driver-short+} supports the following types:

- All {+language+} types that are supported by the ``kotlinx.serialization`` library
- All :manual:`BSON types </reference/bson-types>`

.. _kotlin-sync-add-serialization:

Add the Serialization Dependencies to Your Project
--------------------------------------------------

You must install the official {+language+} serialization library,
``kotlinx.serialization``, to serialize and deserialize data in your
application. To learn more about this library, see the
`kotlinx.serialization GitHub repository
<https://github.com/Kotlin/kotlinx.serialization>`__.

Select from the following tabs to see how to add the serialization
dependencies to your project by using either :guilabel:`Gradle` or
:guilabel:`Maven`:

.. tabs::

.. tab::
:tabid: Gradle

If you are using `Gradle <https://gradle.org/>`__ to manage your
dependencies, add the following to your ``build.gradle.kts``
dependencies list:

.. include:: /includes/data-formats/serialization-gradle-versioned.rst

.. tab::
:tabid: Maven

If you are using `Maven <https://maven.apache.org/>`__ to manage your
dependencies, add the following to your ``pom.xml`` dependencies
list:

.. include:: /includes/data-formats/serialization-maven-versioned.rst

.. 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 {+language+} 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 <{+java-api+}/apidocs/bson-kotlin/index.html>`__.

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

.. _kotlin-sync-data-class-annotation:

Annotate Data Classes
---------------------

To declare a class as serializable, annotate your {+language+} data
classes with the ``@Serializable`` annotation.

You can use your data classes in your code as you use any other data
class after you mark them as serializable. The {+driver-short+} and the
{+language+} serialization framework handle BSON serialization and
deserialization.

This example shows a sample data class with the following annotations:

- ``@Serializable``: Marks the class as serializable.
- ``@SerialName``: Specifies the name of the ``id`` and ``manufacturer`` properties
in the BSON document. This annotation can be used in place of the ``@BsonId`` and
``@BsonProperty`` annotations, which are unsupported in serializable classes.
- ``@Contextual``: Marks the BSON ``id`` property to use the built-in
``ObjectIdSerializer``. This annotation is required for the driver to
serialize BSON types correctly.

.. code-block:: kotlin

@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 = "Grumbacher" // Use instead of @BsonProperty
)

.. note:: POJO Annotations Limitation

You cannot use annotations from the
``org.bson.codecs.pojo.annotations`` package on a data class marked
with the ``@Serializable`` annotation.

To learn more about serializable classes and available annotations,
see `Serializable classes
<https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/basic-serialization.md#serializable-classes>`__
in the ``kotlinx.serialization`` library documentation.

Custom Serializer Example
~~~~~~~~~~~~~~~~~~~~~~~~~

You can create a custom serializer to handle how your data is
represented in BSON. The {+driver-short+} uses the ``KSerializer``
interface from the ``kotlinx.serialization`` library 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``:

.. literalinclude:: /includes/data-formats/serialization.kt
:language: kotlin
:start-after: start-kserializer
:end-before: end-kserializer
:dedent:

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:

.. literalinclude:: /includes/data-formats/serialization.kt
:language: kotlin
:start-after: start-ks-dataclass
:end-before: end-ks-dataclass
:emphasize-lines: 5
:dedent:

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

- `KSerializer
<{+kotlin-docs+}/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-k-serializer/>`__
in the {+language+} documentation

- `Instant
<{+kotlin-docs+}/api/kotlinx-datetime/kotlinx-datetime/kotlinx.datetime/-instant/>`__ in the {+language+} documentation

- `BsonEncoder
<{+java-api+}/apidocs/bson-kotlinx/bson-kotlinx/org.bson.codecs.kotlinx/-bson-encoder/index.html>`__

- `BsonDecoder
<{+java-api+}/apidocs/bson-kotlinx/bson-kotlinx/org.bson.codecs.kotlinx/-bson-decoder/index.html>`__

.. _kotlin-sync-custom-codec:

Customize the Serializer Configuration
--------------------------------------

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 the driver stores in MongoDB.

Use the ``BsonConfiguration`` class to define the configuration,
which can include whether to encode defaults, encode nulls, or define
class discriminators.

To create a custom codec, your project must have the ``bson-kotlinx``
dependency. See the :ref:`kotlin-sync-add-serialization` section of this
guide for installation instructions.

You can define your codec by using the `KotlinSerializerCodec.create()
<{+java-api+}/apidocs/bson-kotlinx/bson-kotlinx/org.bson.codecs.kotlinx/-kotlin-serializer-codec/-companion/index.html>`__
method, then you can add the codec to the registry.

Custom Codec Example
~~~~~~~~~~~~~~~~~~~~

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

.. literalinclude:: /includes/data-formats/serialization.kt
:language: kotlin
:start-after: start-codec
:end-before: end-codec
:dedent:

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

- `KotlinSerializerCodec
<{+java-api+}/apidocs/bson-kotlinx/bson-kotlinx/org.bson.codecs.kotlinx/-kotlin-serializer-codec/index.html>`__

- `KotlinSerializerCodec.create()
<{+java-api+}/apidocs/bson-kotlinx/bson-kotlinx/org.bson.codecs.kotlinx/-kotlin-serializer-codec/-companion/create.html>`__

- `BsonConfiguration
<{+java-api+}/apidocs/bson-kotlinx/bson-kotlinx/org.bson.codecs.kotlinx/-bson-configuration/index.html>`__

.. _kotlin-sync-polymorphic:

Polymorphic Serialization
-------------------------

The {+driver-short+} natively supports serialization and deserialization
of polymorphic classes. When you mark a sealed interface and data
classes that inherit that interface with the ``@Serializable``
annotation, the driver uses a ``KSerializer`` implementation to handle
conversion of your types to and from BSON.

When you insert an instance of a polymorphic data class into MongoDB,
the driver adds the field ``_t``, the
discriminator field. The value of this field is the data class name.

Polymorphic Data Classes Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following example creates an interface and two data classes that
inherit that interface. In the data classes, the ``id`` field is marked
with the annotations described in the
:ref:`kotlin-sync-data-class-annotation` section:

.. literalinclude:: /includes/data-formats/serialization.kt
:language: kotlin
:start-after: start-poly-classes
:end-before: end-poly-classes
:dedent:

Then, you can perform operations with data classes as usual. The
following example parametrizes the collection with the ``Person``
interface, then performs operations with the polymorphic classes
``Teacher`` and ``Student``. When you retrieve documents, the driver
automatically detects the type based on the discriminator value and
deserializes them accordingly.

.. io-code-block::
:copyable: true

.. input:: /includes/data-formats/serialization.kt
:language: kotlin
:start-after: start-poly-operations
:end-before: end-poly-operations
:dedent:

.. output::
:language: console

Retrieving by using data classes
Teacher(id=..., name=Vivian Lee, department=History)
Student(id=..., name=Kate Parker, grade=10)

Retrieving by using Person interface
Teacher(id=..., name=Vivian Lee, department=History)
Student(id=..., name=Kate Parker, grade=10)

Retrieving as Document type
Document{{_id=..., _t=Teacher, name=Vivian Lee, department=History}}
Document{{_id=..., _t=Student, name=Kate Parker, grade=10}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.. code-block:: kotlin
:caption: build.gradle.kts

implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:{+serialization-version+}")
implementation("org.mongodb:bson-kotlinx:{+full-version+}")
13 changes: 13 additions & 0 deletions source/includes/data-formats/serialization-maven-versioned.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. code-block:: xml
:caption: pom.xml

<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-serialization-core</artifactId>
<version>{+serialization-version+}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson-kotlinx</artifactId>
<version>{+full-version+}</version>
</dependency>
Loading
Loading