Serialização Kotlin
Nesta página
- Visão geral
- Tipos suportados
- Adicionar as dependências de serialização ao seu projeto
- Anotar classes de dados
- Exemplo de serializador personalizado
- Personalizar a Configuração do Serializador
- Exemplo de codec personalizado
- Serialização polimórfica
- Exemplo de classes de dados polimórficos
- Serialize datas e horários
- Biblioteca kotlinx-datetime
- Classe de dados de exemplo com datas e horários
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 guiaCodecs .
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.serialization
Todos osBSON types
Adicionar as dependências de serialização ao seu projeto
Você deve instalar a biblioteca oficial de serialização Kotlin , kotlinx.serialization
, para serializar e desserializar dados em seu aplicação. Para saber mais sobre essa biblioteca, consulte o kotlinx.Github repositório de serialização .
Selecione a partir das seguintes abas para ver como adicionar as dependências de serialização ao seu projeto usando Gradle ou Maven:
Se você estiver usando o Gradle para gerenciar suas dependências, adicione o seguinte à sua build.gradle.kts
lista de dependências do :
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1") implementation("org.mongodb:bson-kotlinx:5.2.0")
Se você estiver usando o Maven para gerenciar suas dependências, adicione o seguinte à sua pom.xml
lista de dependências do :
<dependency> <groupId>org.jetbrains.kotlinx</groupId> <artifactId>kotlinx-serialization-core</artifactId> <version>1.5.1</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>bson-kotlinx</artifactId> <version>5.2.0</version> </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
, BsonExtraElements
e 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 propriedadesid
emanufacturer
no documento BSON. Esta anotação pode ser utilizada no lugar das anotações do@BsonId
e@BsonProperty
, que não são suportadas em classes serializáveis.@Contextual
: marca a propriedade BSONid
para usar oObjectIdSerializer
. Essa anotação é necessária para que o driver serialize os BSON types corretamente.
data class PaintOrder( // Use instead of @BsonId val id: ObjectId?, val color: String, val qty: Int, val manufacturer: String = "Grumbacher" // 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 kotlinx.serialization
documentação da biblioteca .
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 kotlinx.datetime.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, 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âneo 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 )
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( 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
Em 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 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}}
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 :
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 saber mais sobre esta 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-datetime
porque o campo tem a anotação@Contextual
.LocalDate
valores 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", }