Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

serialización de datos

Puede utilizar el kotlinx.serialization librería al serializar y deserializar objetos de Kotlin en la aplicación.

El driver ofrece un eficiente serializador Bson que se puede utilizar con clases marcadas con la anotación @Serializable para gestionar la serialización de objetos Kotlin a datos BSON.

Aunque se puede utilizar la librería de serialización de Kotlin Json, el serializador Json no admite directamente tipos de valor BSON como ObjectId. Debes proporcionar un serializador personalizado que pueda gestionar la conversión entre BSON y JSON.

Recomendamos instalar la librería bson-kotlinx para admitir códecs personalizados que tengan configuraciones para codificar valores por defecto, valores nulos y definir discriminadores de clase.

Nota

Para aprender a utilizar la interfaz Codec en lugar de la librería kotlinx.serialization para especificar un comportamiento de serialización personalizado, consulte la Codificar datos con Type Codecs guía.

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.

El controlador de sincronización de Kotlin es compatible con los siguientes tipos:

  • Todos los tipos de Kotlin que son compatibles con la librería kotlinx.serialization

  • Todo BSON types

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 el Registro de Materiales (BOM) del controlador JVM a tu aplicación para gestionar las versiones de los artefactos del controlador. Esto remueve la necesidad de especificar una versión para cualquier paquete individual cubierto por el BOM, simplificando 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.

Selecciona una de las siguientes pestañas para ver cómo agregar las dependencias de serialización a tu proyecto utilizando ya sea Gradle o Maven:

Si usas Gradle para gestionar tus dependencias, añade lo siguiente a tu lista de dependencias de build.gradle.kts:

build.gradle.kts
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.0")
implementation("org.mongodb:bson-kotlinx")

Si usas Maven para gestionar tus dependencias, añade lo siguiente a tu lista de dependencias pom.xml:

pom.xml
<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 bson-kotlin

También puedes instalar opcionalmente la dependencia bson-kotlin a través del registro de códecs por defecto. 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 como BsonDiscriminator, BsonExtraElements y BsonConstructor. Para aprender más, consulte la documentación API de bson-kotlin.

En general, recomendamos que instale y utilice la librería bson-kotlinx más rápida para la configuración de códecs.

Para declarar que una clase es serializable, anota tus clases de datos de 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 marco de serialización de Kotlin gestionan la serialización y deserialización 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 propiedades id y manufacturer en el documento BSON. Esta anotación se puede usar en lugar de las anotaciones @BsonId y @BsonProperty, las cuales no son compatibles en clases serializables.

  • @Contextual: Marca la propiedad BSON id para utilizar la funcionalidad incorporada ObjectIdSerializer. Esta anotación es necesaria para que el driver serialice correctamente los BSON types.

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

Nota

Limitación de anotaciones POJO

No se pueden usar 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 clases serializables y anotaciones disponibles, consulta Clases serializables en la documentación de la librería kotlinx.serialization.

Puedes query las clases de datos anotados utilizando la clase Filters del paquete mongodb-driver-kotlin-extensions. Esta clase te permite crear filtros de query en nombres de campo con la anotación @SerialName.

Tip

Para utilizar la Filters clase de la librería de extensión, debes añadir la dependencia mongodb-driver-kotlin-extensions a tu Proyecto. Para obtener más información, consulte la sección Añadir extensiones de Kotlin a su Proyecto de la guía Utilizar desarrolladores con clases de datos.

El siguiente ejemplo consulta la colección orders para los documentos que tienen 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 query 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 en el nombre del campo especificado en la anotación @SerialName.

Puede crear un serializador personalizado para gestionar cómo se representa su información en BSON. El controlador Kotlin Sync utiliza la interfaz KSerializer de la librería kotlinx.serialization para implementar serializadores personalizados. Puede 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 personalizada de KSerializer 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 serialización personalizada definida en el código anterior:

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

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulta la siguiente documentación de la API:

Puedes usar la clase KotlinSerializerCodec del paquete org.bson.codecs.kotlinx para crear un códec para tus clases de datos @Serializable y personalizar lo que el driver almacena en MongoDB.

Utiliza la clase BsonConfiguration para definir la configuración, que puede incluir si se deben codificar los valores por defecto, codificar los nulos o definir discriminadores de clase.

Para crear un códec personalizado, tu proyecto debe tener la dependencia bson-kotlinx. Consulta la sección Agrega las dependencias de serialización a tu proyecto en esta guía para obtener instrucciones de instalación.

Puedes definir tu códec utilizando el KotlinSerializerCodec.create() método, entonces puedes agregar el códec al registro.

El siguiente ejemplo muestra cómo crear un códec utilizando el método KotlinSerializerCodec.create() y luego configurarlo para no codificar los valores por defecto:

val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>(
bsonConfiguration = BsonConfiguration(encodeDefaults = false)
)
val registry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry
)

Al usar el paquete bson-kotlinx v5.4 o posteriormente, puede indicar al controlador que serialice los nombres de los campos de la clase de datos escritos en camel case a snake case en MongoDB. El siguiente ejemplo muestra cómo crear y registrar un códec personalizado para convertir los nombres de los campos de la clase de datos a snake case al establecer 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, consulta la siguiente documentación de la API:

El driver Kotlin sincronizar admite de forma nativa la serialización y deserialización de clases polimórficas. Cuando marques una interfaz sellada y las clases de datos que heredan de esa interfaz con la anotación @Serializable, el driver utiliza una implementación KSerializer para gestionar la conversión de tus tipos hacia y desde BSON.

Cuando insertas una instancia de una clase de datos polimórfica en MongoDB, o driver añade el campo _t, o campo discriminador. El valor de este campo es el nombre de la clase de datos.

El siguiente ejemplo crea una interfaz y dos clases de datos que heredan de esa interfaz. En las clases de datos, el campo id está marcado con las anotaciones descritas en la sección Anotar clases de datos:

@Serializable
sealed interface Person {
val name: String
}
@Serializable
data class Student(
@Contextual
@SerialName("_id")
val id: ObjectId,
override val name: String,
val grade: Int,
) : Person
@Serializable
data class Teacher(
@Contextual
@SerialName("_id")
val id: ObjectId,
override val name: String,
val department: String,
) : Person

Luego, puedes realizar operaciones con clases de datos como de costumbre. El siguiente ejemplo parametriza la colección con la interfaz Person, luego realiza operaciones con las clases polimorfas Teacher y Student. Cuando se recuperan documentos, el controlador detecta automáticamente el tipo en función del valor 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}}

En esta sección, puedes aprender a utilizar la serialización de Kotlin para trabajar con tipos de fecha y hora.

kotlinx-datetime es una librería de Kotlin que ofrece un alto nivel de control sobre cómo se serializan los valores de fecha y hora. Para usar la librería, agrega la dependencia kotlinx-datetime a la lista de dependencias de tu proyecto.

Seleccione 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:

build.gradle.kts
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")
pom.xml
<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 librería, consulta el Repositorio kotlinx-datetime en GitHub.

Después de agregar la dependencia de la librería, puede implementar los serializadores de la librería kotlinx-datetime que asignan los valores de los campos de la 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 driver serializa el valor como una string.

  • date: El controlador utiliza el serializador kotlinx-datetime porque el campo tiene la anotación @Contextual. LocalDate valores se 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 valores LocalTime.

@Serializable
data class Appointment(
val name: String,
@Contextual 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 por serialización predeterminada:

{
"_id": ...,
"name": "Daria Smith",
"date": {
"$date": "2024-10-15T00:00:00.000Z"
},
"time": "11:30",
}

Volver

Data Formats