Visão geral
Você pode usar a biblioteca kotlinx.serialization ao serializar e desserializar objetos Kotlin em seu aplicação.
O driver fornece um serializador Bson eficiente que você pode usar com classes marcadas com a anotação @Serializable para lidar com a serialização de objetos Kotlin em dados BSON.
Embora você possa usar a Kotlin biblioteca de serialização Json , o Json serializador não oferece suporte direto a BSON tipos de valor , como ObjectId. Você deve fornecer um serializador personalizado que possa lidar com a conversão entre BSON e JSON.
Recomendamos instalar a biblioteca bson-kotlinx para oferecer suporte a codecs personalizados que tenham configurações para codificar padrões, nulos e definir discriminadores de classe .
Observação
Para saber como usar a interface Codec em vez da biblioteca kotlinx.serialization para especificar o comportamento de serialização personalizada, consulte o guia Codificar dados com codecs de tipo.
Você pode optar por usar a serialização do Kotlin se já estiver familiarizado com a biblioteca ou se preferir usar uma abordagem idiomática.
Tipos suportados
O driver do Kotlin Sync é compatível com os seguintes tipos:
Todos os tipos de Kotlin suportados pela biblioteca
kotlinx.serializationTodos os BSON types
Adicionar as dependências de serialização ao seu projeto
Você deve instalar a biblioteca de serialização Kotlin oficial, kotlinx.serialization, para serializar e desserializar dados em seu aplicação. Para saber mais sobre essa biblioteca, consulte o kotlinx. repositório de serialização do Github.
Dica
Lista de materiais
Recomendamos adicionar a Lista de materiais (BOM) do driver JVM ao seu aplicação para gerenciar as versões dos artefatos do driver. Isso elimina a necessidade de especificar uma versão para qualquer pacote individual coberto pelo BOM, simplificando o gerenciamento de dependências. Para saber mais, consulte a etapa Adicionar a lista de materiais do driver do guia de Introdução.
Selecione a partir das seguintes guias para ver como adicionar as dependências de serialização ao seu projeto utilizando Gradle ou Maven:
Se você estiver usando Gradle para gerenciar suas dependências, adicione o seguinte à sua lista de dependências do build.gradle.kts:
build.gradle.kts
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.0")implementation("org.mongodb:bson-kotlinx")Se você estiver usando Maven para gerenciar suas dependências, adicione o seguinte à sua lista de dependências do 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>Observação
bson-kotlin Dependency
Você também pode opcionalmente instalar a dependência do bson-kotlin através do registro de codec padrão. Essa dependência usa a reflexão e o registro do codec para oferecer suporte a classes de dados Kotlin, mas não oferece suporte a determinadas anotações POJO, como BsonDiscriminator, BsonExtraElementse BsonConstructor. Para saber mais, consulte a documentação da API bson-kotlin.
Geralmente, recomendamos que instale e utilize a biblioteca bson-kotlinx mais rápida para configuração de codec.
Anotar classes de dados
Para declarar uma classe como serializável, anote suas classes de dados do Kotlin com a anotação @Serializable .
Você pode usar suas classes de dados em seu código da mesma forma que usa qualquer outra classe de dados depois de marcá-las como serializáveis. O driver Kotlin Sync e a estrutura de serialização do Kotlin lidam com serialização e desserialização BSON.
Este exemplo mostra uma classe de dados de amostra com as seguintes anotações:
@Serializable: Marca a classe como serializável.@SerialName: especifica o nome das propriedadesidemanufacturerno documento BSON. Esta anotação pode ser utilizada no lugar das anotações do@BsonIde@BsonProperty, que não são suportadas em classes serializáveis.@Contextual: marca a propriedade BSONidpara usar oObjectIdSerializer. Essa anotação é necessária para que o driver serialize os BSON types corretamente.
data class PaintOrder( ("_id") // Use instead of @BsonId val id: ObjectId?, val color: String, val qty: Int, ("brand") val manufacturer: String? = null // Use instead of @BsonProperty)Observação
Limitação de anotações POJO
Você não pode utilizar anotações do pacote org.bson.codecs.pojo.annotations em uma classe de dados marcada com a anotação @Serializable .
Para saber mais sobre classes serializáveis e anotações disponíveis, consulte Classes serializáveis na documentação da biblioteca kotlinx.serialization.
Classes anotadas de query
Você pode fazer query de classes de dados anotadas usando a classe Filters do pacote mongodb-driver-kotlin-extensions. Esta classe permite a você criar filtros de query em nomes de campo anotados com a anotação @SerialName.
Dica
Para usar a classe Filters da biblioteca de extensões, você deve adicionar a dependência mongodb-driver-kotlin-extensions ao seu projeto. Para obter mais informações, consulte a seção Adicionar extensões Kotlin ao seu projeto do guia Usar construtores com classes de dados.
O exemplo a seguir faz uma query da collection orders para documentos que tenham um valor de campo brand de "Sherwin-Williams":
val queryFilter = eq(PaintOrder::manufacturer, "Sherwin-Williams")val results = collection.find(queryFilter).toList()O código anterior cria um filtro de query que faz referência à propriedade PaintOrder::manufacturer, mas que query o campo BSON brand. O driver converte automaticamente o nome da propriedade da classe de dados para o nome do campo especificado na anotação @SerialName.
Exemplo de serializador personalizado
Você pode criar um serializador personalizado para lidar com como seus dados são representados no BSON. O driver Kotlin Sync usa a interface KSerializer da biblioteca kotlinx.serialization para implementar serializadores personalizados. Você pode especificar o serializador customizado como parâmetro para a anotação @Serializable para um campo específico.
O exemplo abaixo mostra como criar uma instância personalizada do KSerializer para converter um kotlin.time.Instant para um 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}") } }}O código abaixo mostra a classe de dados PaintOrder na qual o campo orderDate tem uma anotação que especifica a classe de serializador personalizado definida no código anterior:
data class PaintOrder( val color: String, val qty: Int, (with = InstantAsBsonDateTime::class) val orderDate: Instant,)Para saber mais sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:
KSerializer na documentação do Kotlin
Instant na documentação do Kotlin
Personalizar a Configuração do Serializador
Você pode usar a classe KotlinSerializerCodec do pacote org.bson.codecs.kotlinx para criar um codec para suas classes de dados do @Serializable e personalizar o que o driver armazena no MongoDB.
Use a classe BsonConfiguration para definir a configuração, que pode incluir se deseja codificar padrões, codificar nulos ou definir discriminadores de classe .
Para criar um codec personalizado, seu projeto deve ter a dependência bson-kotlinx . Consulte a seção Adicionar as dependências de serialização ao seu projeto deste guia para obter instruções de instalação.
Você pode definir seu codec usando o arquivo KotlinSerializerCodec.create() método, então você pode adicionar o codec ao registro.
Exemplo de codec personalizado
O exemplo seguinte mostra como criar um codec utilizando o método KotlinSerializerCodec.create() e, em seguida, configurá-lo para não codificar padrões:
val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>( bsonConfiguration = BsonConfiguration(encodeDefaults = false))
val registry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry)Implementar estratégia de nomenclatura de caso de cobra
Ao usar o pacote bson-kotlinx v5.4 ou posterior, você pode direcionar o driver para serializar os nomes dos campos de classe de dados escritos em camel case para snake case no MongoDB. O exemplo a seguir mostra como criar e registrar um codec personalizado para converter nomes de campo de classe de dados em caso de cobra configurando o parâmetro bsonNamingStrategy em um codec:
val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>( bsonConfiguration = BsonConfiguration(bsonNamingStrategy = BsonNamingStrategy.SNAKE_CASE))
val registry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry)Para saber mais sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:
Serialização polimórfica
O driver Kotlin Sync suporta nativamente serialização e desserialização de classes polimórficas. Quando você marca uma interface selada e classes de dados que herdam essa interface com a anotação @Serializable , o driver usa uma implementação KSerializer para lidar com a conversão de seus tipos de e para BSON.
Quando você insere uma instância de uma classe de dados polimórficos no MongoDB, o driver adiciona o campo _t, o campo discriminador. O valor deste campo é o nome da classe de dados.
Exemplo de classes de dados polimórficos
O exemplo seguinte cria uma interface e duas classes de dados que herdam esta interface. Nas classes de dados, o campo id é marcado com as anotações descritas na seção Anotar Classes de Dados :
sealed interface Person { val name: String}
data class Student( ("_id") val id: ObjectId, override val name: String, val grade: Int,) : Person
data class Teacher( ("_id") val id: ObjectId, override val name: String, val department: String,) : PersonEm seguida, você pode executar operações com classes de dados como de costume. O exemplo a seguir parametriza a coleção com a interface Person e, em seguida, executa operações com as classes polimórficas Teacher e Student. Ao recuperar documentos, o driver detecta automaticamente o tipo com base no valor do discriminador e os desserializa adequadamente.
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 classesTeacher(id=..., name=Vivian Lee, department=History)Student(id=..., name=Kate Parker, grade=10)
Retrieving by using Person interfaceTeacher(id=..., name=Vivian Lee, department=History)Student(id=..., name=Kate Parker, grade=10)
Retrieving as Document typeDocument{{_id=..., _t=Teacher, name=Vivian Lee, department=History}}Document{{_id=..., _t=Student, name=Kate Parker, grade=10}}Serialize datas e horários
Nesta seção, você pode aprender sobre como usar a serialização do Kotlin para trabalhar com tipos de data e hora.
Biblioteca kotlinx-datetime
kotlinx-datetime é uma biblioteca Kotlin que oferece um alto nível de controle sobre como seus valores de data e hora são serializados. Para utilizar a biblioteca, adicione a dependência kotlinx-datetime à lista de dependência do seu projeto.
Selecione a partir das seguintes guias para ver como adicionar a dependência do kotlinx-datetime ao seu projeto utilizando os gerenciadores de pacote Gradle e 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 saber mais sobre essa biblioteca, consulte o repositório kotlinx-datetime no Github.
Classe de dados de exemplo com datas e horários
Após adicionar a dependência da biblioteca, você pode implementar serializadores da biblioteca do kotlinx-datetime que mapeiam seus valores de campo de classe de dados para os tipos esperados no BSON.
Neste exemplo, o driver serializa os campos da classe de dados Appointment com o seguinte comportamento:
name: o driver serializa o valor como uma string.date: o driver utiliza o serializadorkotlinx-datetimeporque o campo tem a anotação@Contextual.LocalDatevalores são serializados como datas BSON.time: o driver serializa o valor como uma string porque ele não tem a anotação@Contextual. Este é o comportamento de serialização padrão para valoresLocalTime.
data class Appointment( val name: String, val date: LocalDate, val time: LocalTime,)O exemplo seguinte insere uma instância da classe de dados Appointment na coleção appointments :
val collection = database.getCollection<Appointment>("appointments")
val apptDoc = Appointment( "Daria Smith", LocalDate(2024, 10, 15), LocalTime(hour = 11, minute = 30))
collection.insertOne(apptDoc)No MongoDB, o valor LocalDate é armazenado como uma data BSON e o campo time é armazenado como uma string por serialização padrão:
{ "_id": ..., "name": "Daria Smith", "date": { "$date": "2024-10-15T00:00:00.000Z" }, "time": "11:30",}