Overview
Puedes utilizar el kotlinx.serialization biblioteca al serializar y deserializar objetos Kotlin en su aplicación.
El controlador proporciona un serializador Bson eficiente que puede utilizar con clases marcadas con la anotación @Serializable para manejar la serialización de objetos Kotlin en datos BSON.
Aunque puede usar la Json biblioteca de serialización de Kotlin, el Json serializador no admite directamente tipos de valor BSON ObjectId como. Debe proporcionar un serializador personalizado que pueda gestionar la conversión entre BSON y JSON.
Recomendamos instalar la biblioteca bson-kotlinx para admitir códecs personalizados que tengan configuraciones para codificar valores predeterminados, nulos y definir discriminadores de clase.
Nota
Para aprender a usar la interfaz Codec en lugar de la biblioteca kotlinx.serialization para especificar un comportamiento de serialización personalizado, consulte la Guía decodificación de datos con códecs de tipo.
Podrías optar por utilizar la serialización de Kotlin si ya estás familiarizado con la librería o si prefieres utilizar un enfoque idiomático.
Tipos admitidos
El controlador Kotlin Sync admite los siguientes tipos:
Todos los tipos de Kotlin que son compatibles con la librería
kotlinx.serializationTodo BSON types
Agregue las dependencias de serialización a su proyecto
Debes instalar la librería oficial de serialización de Kotlin, kotlinx.serialization, para serializar y deserializar datos en tu aplicación. Para aprender más sobre esta librería, consulta el repositorio GitHub de kotlinx.serialization.
Tip
Lista de materiales
Recomendamos agregar la lista de materiales (BOM) del controlador JVM a su aplicación para administrar las versiones de los artefactos del controlador. Esto elimina la necesidad de especificar una versión para cada paquete individual cubierto por la BOM, lo que simplifica la gestión de dependencias. Para obtener más información, consulte el paso "Agregar la lista de materiales del controlador" de la guía de introducción.
Seleccione una de las siguientes pestañas para ver cómo agregar las dependencias de serialización a su proyecto utilizando Gradle o Maven:
Si está utilizando Gradle para administrar sus dependencias, agregue lo siguiente a su build.gradle.kts lista de dependencias:
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.0") implementation("org.mongodb:bson-kotlinx")
Si está utilizando Maven para administrar sus dependencias, agregue lo siguiente a su pom.xml lista de dependencias:
<dependency> <groupId>org.jetbrains.kotlinx</groupId> <artifactId>kotlinx-serialization-core</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>bson-kotlinx</artifactId> </dependency>
Nota
Dependencia de bson-kotlin
También puede instalar opcionalmente la bson-kotlin dependencia a través del registro de códecs predeterminado. Esta dependencia utiliza la reflexión y el registro de códecs para admitir las clases de datos de Kotlin, pero no admite ciertas anotaciones POJO BsonDiscriminator BsonExtraElementscomo,BsonConstructor y. Para obtener más información, consulte la documentación de la API bson-kotlin.
En general, recomendamos que instale y utilice la biblioteca bson-kotlinx más rápida para la configuración del códec.
Anotar clases de datos
Para declarar una clase como serializable, anote sus clases de datos Kotlin con la anotación @Serializable.
Puedes usar tus clases de datos en tu código como cualquier otra clase de datos después de marcarlas como serializables. El controlador Kotlin Sync y el framework de serialización de Kotlin gestionan la serialización y deserialización de BSON.
Este ejemplo muestra una clase de datos de ejemplo con las siguientes anotaciones:
@Serializable: Marca la clase como serializable.@SerialName: Especifica el nombre de las propiedadesidymanufactureren el documento BSON. Esta anotación puede utilizarse en lugar de las anotaciones@BsonIdy@BsonProperty, que no son compatibles con las clases serializables.@ContextualMarca la propiedad BSONidpara usar la propiedad integradaObjectIdSerializer. Esta anotación es necesaria para que el controlador serialice correctamente los tipos BSON.
data class PaintOrder( // Use instead of @BsonId val id: ObjectId?, val color: String, val qty: Int, val manufacturer: String? = null // Use instead of @BsonProperty )
Nota
Limitación de las anotaciones POJO
No se pueden utilizar anotaciones del paquete org.bson.codecs.pojo.annotations en una clase de datos marcada con la anotación @Serializable.
Para obtener más información sobre las clases serializables y las anotaciones disponibles, consulte Clases serializables en la kotlinx.serialization documentación de la biblioteca.
Clases anotadas de consulta
Puede consultar clases de datos anotadas mediante la clase Filtros del mongodb-driver-kotlin-extensions paquete. Esta clase permite crear filtros de consulta para nombres de campo anotados con la @SerialName anotación.
Tip
Para usar la Filters clase de la biblioteca de extensiones, debe agregar la mongodb-driver-kotlin-extensions dependencia a su proyecto. Para obtener más información, consulte la sección "Agregar extensiones de Kotlin a su proyecto" de la guía "Usar constructores con clases de datos".
El siguiente ejemplo consulta la colección orders en busca de documentos que tengan un valor de campo brand de "Sherwin-Williams":
val queryFilter = eq(PaintOrder::manufacturer, "Sherwin-Williams") val results = collection.find(queryFilter).toList()
El código anterior crea un filtro de consulta que hace referencia a la propiedad PaintOrder::manufacturer, pero consulta el campo BSON brand. El controlador convierte automáticamente el nombre de la propiedad de la clase de datos al nombre del campo especificado en la anotación @SerialName.
Ejemplo de serializador personalizado
Puedes crear un serializador personalizado para gestionar la representación de tus datos en BSON. El controlador de sincronización de Kotlin utiliza la interfaz KSerializer de la biblioteca kotlinx.serialization para implementar serializadores personalizados. Puedes especificar el serializador personalizado como parámetro de la anotación @Serializable para un campo específico.
El siguiente ejemplo muestra cómo crear una instancia KSerializer personalizada para convertir un kotlin.time.Instant en un 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.toEpochMilli())) else -> throw SerializationException("Instant is not supported by ${encoder::class}") } } override fun deserialize(decoder: Decoder): Instant { return when (decoder) { is BsonDecoder -> Instant.ofEpochMilli(decoder.decodeBsonValue().asDateTime().value) else -> throw SerializationException("Instant is not supported by ${decoder::class}") } } }
El siguiente código muestra la clase de datos PaintOrder en la que el campo orderDate tiene una anotación que especifica la clase de serializador personalizado definida en el código anterior:
data class PaintOrder( val color: String, val qty: Int, val orderDate: Instant, )
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
KSerializer en la documentación de Kotlin
Instantáneo en la documentación de Kotlin
Personalizar la configuración del serializador
Puede utilizar la clase KotlinSerializerCodec del paquete org.bson.codecs.kotlinx para crear un códec para sus clases de datos @Serializable y personalizar lo que el controlador almacena en MongoDB.
Utilice la clase BsonConfiguration para definir la configuración, que puede incluir si codificar valores predeterminados, codificar valores nulos o definir discriminadores de clase.
Para crear un códec personalizado, su proyecto debe tener la dependencia. Consulte la bson-kotlinx sección "Añadir las dependencias de serialización a su proyecto" de esta guía para obtener instrucciones de instalación.
Puede definir su códec utilizando el método KotlinSerializerCodec.create() y luego puede agregar el códec al registro.
Ejemplo de códec personalizado
El siguiente ejemplo muestra cómo crear un códec utilizando el KotlinSerializerCodec.create() método y luego configurarlo para no codificar valores predeterminados:
val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>( bsonConfiguration = BsonConfiguration(encodeDefaults = false) ) val registry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry )
Implementar la estrategia de nombres de casos de serpiente
Al usar el paquete bson-kotlinx v5.4 o posterior, puede indicar al controlador que serialice los nombres de los campos de clase de datos escritos en CamelCase a SnakeCase en MongoDB. El siguiente ejemplo muestra cómo crear y registrar un códec personalizado para convertir los nombres de los campos de clase de datos a SnakeCase mediante el parámetro bsonNamingStrategy en un códec:
val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>( bsonConfiguration = BsonConfiguration(bsonNamingStrategy = BsonNamingStrategy.SNAKE_CASE) ) val registry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry )
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Serialización polimórfica
El controlador Kotlin Sync admite de forma nativa la serialización y deserialización de clases polimórficas. Al marcar una interfaz sellada y las clases de datos que heredan dicha interfaz con la anotación @Serializable, el controlador utiliza una implementación KSerializer para gestionar la conversión de los tipos a y desde BSON.
Al insertar una instancia de una clase de datos polimórfica en MongoDB, el controlador agrega el campo _t, el campo discriminador. El valor de este campo es el nombre de la clase de datos.
Ejemplo de Clases de Datos Polimórficos
El siguiente ejemplo crea una interfaz y dos clases de datos que heredan dicha interfaz. En las clases de datos, el id campo se marca con las anotaciones descritas en la sección "Anotar clases de datos":
sealed interface Person { val name: String } data class Student( val id: ObjectId, override val name: String, val grade: Int, ) : Person data class Teacher( val id: ObjectId, override val name: String, val department: String, ) : Person
A continuación, puede realizar operaciones con las clases de datos de la forma habitual. El siguiente ejemplo parametriza la colección con la interfaz Person y, a continuación, realiza operaciones con las clases polimórficas Teacher y Student. Al recuperar documentos, el controlador detecta automáticamente el tipo según el valor del discriminador y los deserializa en consecuencia.
val collection = database.getCollection<Person>("school") val teacherDoc = Teacher(ObjectId(), "Vivian Lee", "History") val studentDoc = Student(ObjectId(), "Kate Parker", 10) collection.insertOne(teacherDoc) collection.insertOne(studentDoc) println("Retrieving by using data classes") val resultTeacher = collection.withDocumentClass<Teacher>() .find(Filters.exists("department")) .firstOrNull() println(resultTeacher) val resultStudent = collection.withDocumentClass<Student>() .find(Filters.exists("grade")) .firstOrNull() println(resultStudent) println("\nRetrieving by using Person interface") val resultsPerson = collection.withDocumentClass<Person>().find() resultsPerson.forEach { result -> println(result) } println("\nRetrieving as Document type") val resultsDocument = collection.withDocumentClass<Document>().find() resultsDocument.forEach { result -> println(result) }
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}}
Serializar fechas y horas
En esta sección, puede aprender a usar la serialización de Kotlin para trabajar con tipos de fecha y hora.
Biblioteca kotlinx-datetime
kotlinx-datetime Es una biblioteca de Kotlin que ofrece un alto nivel de control sobre la serialización de los valores de fecha y hora. Para usarla, añada la dependencia kotlinx-datetime a la lista de dependencias de su proyecto.
Seleccione una de las siguientes pestañas para ver cómo agregar la dependencia kotlinx-datetime a su proyecto utilizando los administradores de paquetes Gradle y Maven:
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")
<dependency> <groupId>org.jetbrains.kotlinx</groupId> <artifactId>kotlinx-datetime-jvm</artifactId> <version>0.6.1</version> </dependency>
Para obtener más información sobre esta biblioteca, consulte el repositorio kotlinx-datetime en GitHub.
Ejemplo de clase de datos con fechas y horas
Después de agregar la dependencia de la biblioteca, puede implementar serializadores de la biblioteca kotlinx-datetime que asignan los valores de los campos de clase de datos a los tipos esperados en BSON.
En este ejemplo, el driver serializa los campos de la clase de datos Appointment con el siguiente comportamiento:
name:El controlador serializa el valor como una cadena.date:El controlador utiliza el serializadorkotlinx-datetimeporque el campo tiene la anotación@Contextual. Los valoresLocalDatese serializan como fechas BSON.time: El driver serializa el valor como una string porque no tiene la anotación@Contextual. Este es el comportamiento de serialización por defecto para los valoresLocalTime.
data class Appointment( val name: String, val date: LocalDate, val time: LocalTime, )
El siguiente ejemplo inserta una instancia de la clase de datos Appointment en la colección appointments:
val collection = database.getCollection<Appointment>("appointments") val apptDoc = Appointment( "Daria Smith", LocalDate(2024, 10, 15), LocalTime(hour = 11, minute = 30) ) collection.insertOne(apptDoc)
En MongoDB, el valor LocalDate se almacena como una fecha BSON y el campo time se almacena como una cadena mediante la serialización predeterminada:
{ "_id": ..., "name": "Daria Smith", "date": { "$date": "2024-10-15T00:00:00.000Z" }, "time": "11:30", }