Serialização Kotlin
Nesta página
Visão geral
Você pode usar a biblioteca kotlinx.serialization
ao serializar e desserializar objetos Kotlin em seu aplicativo.
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 biblioteca de Json
Json
, o serializador não oferece suporte direto a tipos de valor ObjectId
, como . 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 ostipos de BSON do
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 aplicativo. Para saber mais sobre essa biblioteca, consulte o repositório kotlinx.serialization do GitHub.
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.1.4")
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.1.4</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 tipos BSON 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}}