Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.

Codificar dados com codecs de tipo

Neste guia, você pode aprender sobre Codecs e classes de suporte que lidam com a codificação e decodificação de objetos Kotlin de e para dados BSON. A abstração do Codec permite mapear qualquer tipo Kotlin para um tipo BSON correspondente. Você pode usar esse recurso para mapear seus objetos de domínio diretamente de e para o BSON, em vez de usar classes como Document ou BsonDocument.

Você pode aprender a especificar a lógica de codificação e decodificação personalizada usando a Codec abstração e exibir implementações de exemplo nas seções a seguir:

Dica

Serialização Kotlin

Você pode usar a serialização do Kotlin para lidar com a codificação e decodificação de dados com classes @Serializable em vez de implementar codecs personalizados. Você pode escolher a serialização do Kotlin se já estiver familiarizado com a biblioteca kotlinx.serialization ou preferir usar uma abordagem idiomática do Kotlin . Para saber mais, consulte o guia Serialização de dados.

A interface do Codec contém métodos abstratos para serializar e desserializar objetos Kotlin para dados BSON. Você pode definir a lógica de conversão personalizada em sua implementação desta interface.

Para implementar a interface do Codec, substitua os métodos abstratos encode(), decode() e getEncoderClass().

O método encode() exige os seguintes parâmetros:

Parameter Type
Descrição

writer

Uma instância de uma classe que implementa o BsonWriter, um tipo de interface que expõe métodos para escrever um documento BSON. Por exemplo, a implementação do BsonBinaryWriter grava em um fluxo binário de dados. Use esta instância para escrever seu valor BSON usando o método de escrita apropriado.

value

Os dados que sua implementação codifica. O tipo deve corresponder à variável de tipo atribuída à sua implementação.

encoderContext

Contém metainformações sobre os dados de objeto Kotlin que codifica para BSON, incluindo se deve armazenar o valor atual em uma coleção MongoDB .

O método encode() utiliza a instância BsonWriter para enviar o valor codificado para MongoDB e não retorna um valor.

O método decode() retorna sua instância de objeto Kotlin preenchida com o valor dos dados BSON. Este método requer os seguintes parâmetros:

Parameter Type
Descrição

reader

Uma instância de uma classe que implementa o BsonReader, um tipo de interface que expõe métodos para ler um documento BSON. Por exemplo, a implementação do BsonBinaryReader lê a partir de um fluxo binário de dados.

decoderContext

Contém informações sobre os dados BSON que decodifica para um objeto Kotlin.

O método getEncoderClass() retorna uma instância de classe Kotlin uma vez que Kotlin não pode inferir o tipo devido ao apagamento do tipo.

Esta seção contém exemplos de código que mostram como você pode implementar uma interface Codec personalizada.

O enumeração PowerStatus contém os valores "ON" e "OFF" para representar os estados de um interruptor elétrico:

enum class PowerStatus { ON, OFF}

A classe PowerStatusCodec implementa a interface Codec para converter os valores Kotlin enum em valores booleanos BSON correspondentes. O método encode() converte um valor PowerStatus em um booleano BSON e o método decode() executa a conversão na direção oposta.

class PowerStatusCodec : Codec<PowerStatus> { override fun encode( writer: BsonWriter, value: PowerStatus, encoderContext: EncoderContext ) = writer.writeBoolean(value == PowerStatus.ON) override fun decode( reader: BsonReader, decoderContext: DecoderContext) : PowerStatus { return when (reader.readBoolean()) { true -> PowerStatus.ON false -> PowerStatus.OFF } } override fun getEncoderClass(): Class<PowerStatus> = PowerStatus::class.java}

Você pode adicionar uma instância de PowerStatusCodec ao seu CodecRegistry. Consulte a seção CodecRegistry desta página para saber como incluir seu Codec em seu registro.

Para saber mais sobre as classes e interfaces mencionadas nesta seção, consulte a seguinte documentação da API:

Um CodecRegistry é uma coleção imutável de instâncias do Codec que codificam e decodificam classes Kotlin . Você pode usar qualquer um dos seguintes métodos de fábrica estática de classe CodecRegistries para construir uma CodecRegistry a partir das instâncias Codec contidas nos tipos associados:

  • fromCodecs(): Cria um registro a partir de instâncias de Codec

  • fromProviders(): Cria um registro a partir de instâncias de CodecProvider

  • fromRegistries(): Cria um registro a partir de instâncias de CodecRegistry

O seguinte código mostra como construir um CodecRegistry utilizando o método fromCodecs() :

val codecRegistry = CodecRegistries .fromCodecs(IntegerCodec(), PowerStatusCodec())

O exemplo anterior atribui ao CodecRegistry as seguintes implementações do Codec :

  • IntegerCodec: Codec que converte Integers. Faz parte do pacote BSON.

  • PowerStatusCodec: Exemplo Codec da seção anterior que converte valores de enumeração do Kotlin em booleanos BSON.

Você pode recuperar as instâncias Codec da instância CodecRegistry usando o código a seguir:

val powerStatusCodec = codecRegistry.get(PowerStatus::class.java)val integerCodec = codecRegistry.get(Integer::class.java)

Se você tentar recuperar uma instância do Codec para uma classe que não está registrada, o método do codecRegistry.get() gerará uma exceção do CodecConfigurationException .

Para obter mais informações sobre as classes e interfaces nesta seção, consulte a seguinte Documentação da API:

Um CodecProvider é uma interface que contém métodos abstratos para criar instâncias do Codec e atribuí-las a instâncias do CodecRegistry . Semelhante à interface CodecRegistry , a biblioteca BSON usa as instâncias do Codec recuperadas pelo método CodecProvider.get() para converter entre Kotlin e tipos de dados BSON.

No entanto, nos casos em que você adicionar uma classe que contém campos que exigem objetos Codec correspondentes, certifique-se de instanciar os objetos Codec para os campos da classe antes de instanciar o Codec para a classe inteira. Você pode utilizar o parâmetro CodecRegistry no método CodecProvider.get() para passar qualquer uma das instâncias do Codec em que o Codec confia.

Para visualizar um exemplo executável que demonstra operações de leitura e escrita utilizando classes Codec , consulte a seção Exemplo de codec personalizado deste guia.

O registro de codec padrão é um definir de classes CodecProvider que especificam a conversão entre objetos Kotlin comumente usados e tipos MongoDB . O driver usa automaticamente o registro de codec padrão, a menos que você especifique um registro diferente.

Para substituir o comportamento de uma ou mais classes Codec , mas manter o comportamento do registro de codecs padrão para as outras classes, você pode especificar os registros em ordem de precedência. Por exemplo, suponha que você queira substituir o comportamento padrão do provedor de um Codec para tipos de enumeração pelo seu MyEnumCodec personalizado . Você deve adicioná-lo à lista de registros em uma posição antes do registro de codec padrão, conforme mostrado no exemplo a seguir:

val newRegistry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(MyEnumCodec()), MongoClientSettings.getCodecRegistry())

Para obter mais informações sobre as classes e interfaces nesta seção, consulte a seguinte Documentação da API:

A classe BsonTypeClassMap contém um mapeamento recomendado entre os tipos BSON e Kotlin . Você pode usar essa classe em seu Codec ou CodecProvider personalizado para ajudá-lo a gerenciar para quais tipos de Kotlin decodificar seus BSON types . Ele também contém classes de container que implementam Iterable ou Map , como a classe Document .

Você pode adicionar ou modificar o mapeamento padrão do BsonTypeClassMap passando um Map contendo entradas novas ou de substituição.

O código a seguir mostra como recuperar o tipo de classe Kotlin que corresponde ao tipo de array BSON na instância BsonTypeClassMap padrão:

val bsonTypeClassMap = BsonTypeClassMap()val clazz = bsonTypeClassMap[BsonType.ARRAY]println("Kotlin class name: " + clazz.name)
Kotlin class name: java.util.List

Você pode modificar esses mapeamentos na sua instância especificando substituições no construtor BsonTypeClassMap . O snippet de código a seguir mostra como você pode substituir o mapeamento do tipo array BSON em sua BsonTypeClassMap instância pela Set classe :

val replacements = mutableMapOf<BsonType, Class<*>>(BsonType.ARRAY to MutableSet::class.java)val bsonTypeClassMap = BsonTypeClassMap(replacements)val clazz = bsonTypeClassMap[BsonType.ARRAY]println("Class name: " + clazz.name)
Kotlin class name: java.util.Set

Para obter uma lista completa dos mapeamentos padrão, consulte a documentação da API BsonTypeClassMap.

Esta seção demonstra como você pode implementar interfaces do Codec e CodecProvider para definir a lógica de codificação e decodificação de uma classe Kotlin personalizada. Ele mostra como você pode especificar e usar suas implementações personalizadas para realizar operações de leitura e escrita.

O seguinte código define a classe de dados de amostra Monolight:

data class Monolight( var powerStatus: PowerStatus = PowerStatus.OFF, var colorTemperature: Int? = null) { override fun toString(): String = "Monolight { powerStatus: $powerStatus, colorTemperature: $colorTemperature }"}

Esta classe contém os seguintes campos que cada um exige um Codec correspondente para lidar com a codificação e decodificação:

  • powerStatus: descreve se a luz do dispositivo é "ON" ou "OFF". Para este campo, use o PowerStatusCodec que converte os valores de enumeração do PowerStatus para booleanos BSON.

  • colorTemperature: descreve a cor da luz do dispositivo em celvins como um valor Int . Para este campo, utilize o IntegerCodec fornecido na biblioteca BSON.

O seguinte código mostra como implementar um Codec para a classe Monolight . O construtor espera uma instância de CodecRegistry da qual ele recupera as instâncias de Codec necessárias para codificar e decodificar os campos de classe :

class MonolightCodec(registry: CodecRegistry) : Codec<Monolight> { private val powerStatusCodec: Codec<PowerStatus> private val integerCodec: Codec<Int> init { powerStatusCodec = registry[PowerStatus::class.java] integerCodec = IntegerCodec() } override fun encode(writer: BsonWriter, value: Monolight, encoderContext: EncoderContext) { writer.writeStartDocument() writer.writeName("powerStatus") powerStatusCodec.encode(writer, value.powerStatus, encoderContext) writer.writeName("colorTemperature") integerCodec.encode(writer, value.colorTemperature, encoderContext) writer.writeEndDocument() } override fun decode(reader: BsonReader, decoderContext: DecoderContext): Monolight { val monolight = Monolight() reader.readStartDocument() while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { when (reader.readName()) { "powerStatus" -> monolight.powerStatus = powerStatusCodec.decode(reader, decoderContext) "colorTemperature" -> monolight.colorTemperature = integerCodec.decode(reader, decoderContext) "_id" -> reader.readObjectId() } } reader.readEndDocument() return monolight } override fun getEncoderClass(): Class<Monolight> = Monolight::class.java}

Para garantir que as instâncias Codec dos campos estejam disponíveis para a classe Monolight , implemente um CodecProvider personalizado conforme mostrado no exemplo de código a seguir :

class MonolightCodecProvider : CodecProvider { @Suppress("UNCHECKED_CAST") override fun <T> get(clazz: Class<T>, registry: CodecRegistry): Codec<T>? { return if (clazz == Monolight::class.java) { MonolightCodec(registry) as Codec<T> } else null // Return null when not a provider for the requested class }}

Após definir a lógica de conversão, você pode executar as seguintes ações:

  • Armazenar instâncias de Monolight no MongoDB

  • Recuperar documentos do MongoDB como instâncias de Monolight

O código a seguir atribui o MonolightCodecProvider à instância MongoCollection passando-o para o método withCodecRegistry() . A classe de exemplo também insere e recupera dados utilizando a classe Monolight :

val mongoClient = MongoClient.create(uri) val codecRegistry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(IntegerCodec(), PowerStatusCodec()), CodecRegistries.fromProviders(MonolightCodecProvider()), MongoClientSettings.getDefaultCodecRegistry() ) val database = mongoClient.getDatabase("codec_test") val collection = database.getCollection<Monolight>("monolights") .withCodecRegistry(codecRegistry) // Insert instances of Monolight val monolights = listOf( Monolight(PowerStatus.ON, 5200), Monolight(PowerStatus.OFF, 3000) ) collection.insertMany(monolights) // Retrieve instances of Monolight val results = collection.find() results.forEach { l -> println(l) }
Monolight { powerStatus: ON, colorTemperature: 5200 }Monolight { powerStatus: OFF, colorTemperature: 3000 }

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API: