Para agentes de IA: hay un índice de documentación disponible en https://www.mongodb.com/es/docs/llms.txt — versiones en markdown de todas las páginas están disponibles agregando .md a cualquier ruta URL.
Docs Menu

Codifica datos con códecs de tipo

En esta guía, puede aprender sobre los códecs y las clases de soporte que gestionan la codificación y decodificación de objetos Scala hacia y desde datos BSON en el driver de Scala. La abstracción Codec le permite asignar cualquier tipo de Scala a un tipo BSON correspondiente. Utilice esto para asignar sus objetos de dominio directamente hacia y desde BSON en lugar de depender de un objeto intermedio basado en mapas como Document o BsonDocument.

La interfaz Codec contiene métodos abstractos para codificar y decodificar objetos Scala hacia y desde datos BSON. Implementar estos métodos para definir la lógica de conversión entre BSON y el tipo Scala de su implementación Codec.

To implement the Codec interface, define the interface's encode(), decode(), and getEncoderClass() methods. To see a code example that implements these methods, see the Basic Custom Codec Example section.

El método encode() codifica una instancia del tipo Scala en BSON para que el driver pueda almacenarla en MongoDB. Este método requiere los siguientes parámetros:

Parameter Type
Descripción

writer

Una instancia de una clase que implementa BsonWriter, una interfaz que expone métodos para guardar un documento BSON. Utilice esta instancia para guardar su valor BSON utilizando el método de guardar apropiado para su tipo de valor BSON.

value

Los datos que codifica el método. El tipo value debe coincidir con el parámetro de tipo que asignó a su implementación Codec.

encoderContext

Metadatos sobre el objeto Scala que el método codifica en BSON, incluyendo si se debe almacenar el valor actual en una colección de MongoDB.

El método encode() no devuelve un valor.

El método decode() utiliza los datos BSON para decodificar una instancia del tipo Scala. Este método requiere los siguientes parámetros:

Parameter Type
Descripción

bsonReader

Una instancia de una clase que implementa BsonReader, una interfaz que expone métodos para leer un documento BSON.

decoderContext

Metadatos sobre los datos BSON que el método decodifica en un objeto Scala.

El método getEncoderClass() devuelve una instancia del tipo Scala definido en el Codec. Este método proporciona la información de tipo que la máquina virtual de Java (JVM) borra en tiempo de ejecución.

Las siguientes muestras de código utilizan la característica sellada PowerStatus y la clase PowerStatusCodec para mostrar cómo se puede implementar un Codec personalizado.

La característica sellada PowerStatus utiliza los objetos de caso On y Off para representar los estados de un interruptor eléctrico:

sealed trait PowerStatus
object PowerStatus {
case object On extends PowerStatus
case object Off extends PowerStatus
}

La clase PowerStatusCodec implementa la interfaz Codec para codificar valores PowerStatus en los valores booleanos de BSON correspondientes. El método encode() codifica un valor PowerStatus en un valor booleano de BSON y el método decode() decodifica un valor booleano de BSON en un valor PowerStatus.

class PowerStatusCodec extends Codec[PowerStatus] {
override def encode(writer: BsonWriter, value: PowerStatus,
encoderContext: EncoderContext): Unit = {
if (value != null) {
writer.writeBoolean(value == PowerStatus.On)
}
}
override def decode(reader: BsonReader,
decoderContext: DecoderContext): PowerStatus = {
if (reader.readBoolean()) PowerStatus.On else PowerStatus.Off
}
override def getEncoderClass: Class[PowerStatus] = classOf[PowerStatus]
}

To use the PowerStatusCodec class, you must add an instance of the class to your CodecRegistry interface, which maps your Codec to the corresponding Scala type. The driver can encode and decode a type only if the CodecRegistry contains a Codec for that type. To learn how to include your custom Codec in your CodecRegistry interface, see the CodecRegistry section of this page.

Para obtener más información sobre las clases y las interfaces de esta sección, consulta la siguiente documentación de la API:

Un CodecRegistry es una colección inmutable de Codec instancias. Para construir una instancia de CodecRegistry, utilice uno de los siguientes métodos de fábrica estática de clase CodecRegistries. Cada método compila el registro a partir de una fuente diferente de Codec instancias:

Método
Descripción

fromCodecs()

Compila un registro a partir de las instancias Codec que pasa al método

fromProviders()

Compila un registro a partir de las instancias Codec que proporcionan las instancias CodecProvider que se pasan al método

fromRegistries()

Compila un registro combinando las otras instancias de CodecRegistry que se pasan al método

Los siguientes ejemplos utilizan dos implementaciones Codec:

  • IntegerCodec: Un Codec en el paquete BSON que codifica valores Integer de Java en valores enteros de 32bits de BSON.

  • PowerStatusCodec: A sample Codec that decodes PowerStatus values to BSON Booleans.

El siguiente ejemplo muestra cómo construir una instancia de CodecRegistry utilizando el método fromCodecs() para asignar estas implementaciones al registro:

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

El siguiente ejemplo recupera las instancias Codec del ejemplo anterior de la colección CodecRegistry:

val powerStatusCodec: Codec[PowerStatus] =
codecRegistry.get(classOf[PowerStatus])
val integerCodec: Codec[Integer] =
codecRegistry.get(classOf[Integer])

Nota

Si llama al método get() en una instancia Codec para una clase no registrada, el driver arroja un CodecConfigurationException.

The default codec registry is a set of CodecProvider classes that encode between commonly used Scala and MongoDB types. The driver automatically uses the default codec registry unless you specify a custom codec registry. To learn more about the CodecProvider interface, see the CodecProvider section.

Si debe anular el comportamiento de una o más clases Codec, pero desea mantener el comportamiento del registro de códec por defecto para las otras clases, puede especificar todos los registros en orden de precedencia. Por ejemplo, para anular el comportamiento del proveedor predeterminado de un Codec para un tipo personalizado con su MyEnumCodec, agréguelo a la lista de registros antes del registro de códec predeterminado. El siguiente ejemplo muestra este patrón:

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

Para obtener más información sobre las clases y las interfaces de esta sección, consulta la siguiente documentación de la API:

La interfaz CodecProvider contiene métodos abstractos que crean instancias Codec y las asignan a una instancia CodecRegistry. Al igual que la interfaz CodecRegistry, la interfaz CodecProvider define un método get() que devuelve instancias Codec. La librería BSON utiliza estas instancias Codec para codificar entre Scala y los tipos de datos BSON.

Utilice un CodecProvider cuando agregue una clase a su código cuyos campos necesiten los objetos Codec correspondientes. Cuando cada campo requiere su propia instancia Codec, debe crear una instancia de los objetos Codec para cada campo antes de crear una instancia de la instancia Codec para la clase. Utilice el parámetro CodecRegistry en el método get() para pasar cualquiera de las instancias Codec en las que se basa el Codec a un constructor.

El siguiente ejemplo muestra cómo implementar una interfaz CodecProvider. El driver utiliza la interfaz MonolightCodecProvider implementada para crear una instancia MonolightCodec para la clase Monolight.

class MonolightCodecProvider extends CodecProvider {
override def get[T](clazz: Class[T], registry: CodecRegistry): Codec[T] = {
if (clazz == classOf[Monolight]) {
new MonolightCodec(registry).asInstanceOf[Codec[T]]
} else {
null
}
}
}

For a complete implementation of a CodecProvider interface, including custom classes, see the Complete Custom Codec Example section of this guide.

Para obtener más información sobre las clases y las interfaces de esta sección, consulta la siguiente documentación de la API:

En esta sección, puedes aprender a implementar las interfaces Codec y CodecProvider para definir la lógica de codificación y decodificación de una clase Scala personalizada. En esta sección también se muestra cómo especificar y utilizar sus implementaciones personalizadas para realizar operaciones de inserción y recuperación.

El siguiente snippet de código muestra la clase personalizada de ejemplo Monolight y sus campos:

case class Monolight(
powerStatus: PowerStatus = PowerStatus.Off,
colorTemperature: Int = 0
)

La clase Monolight contiene los siguientes campos, cada uno de los cuales requiere una implementación de interfaz Codec:

  • powerStatus describes if the light is switched on or off. The PowerStatusCodec class encodes PowerStatus values to BSON Booleans.

  • colorTemperature describe el color de la luz y contiene un valor Int. La clase IntegerCodec incluida en la librería BSON codifica valores colorTemperature en enteros BSON de 32bits.

El siguiente ejemplo de código muestra cómo implementar una interfaz Codec para la clase Monolight. El constructor utiliza una instancia de CodecRegistry para recuperar las instancias de Codec que necesita para codificar y decodificar los campos de Monolight.

class MonolightCodec(registry: CodecRegistry) extends Codec[Monolight] {
private val powerStatusCodec: Codec[PowerStatus] =
registry.get(classOf[PowerStatus])
private val integerCodec: Codec[Integer] =
registry.get(classOf[Integer])
override def encode(writer: BsonWriter, value: Monolight,
encoderContext: EncoderContext): Unit = {
writer.writeStartDocument()
writer.writeName("powerStatus")
powerStatusCodec.encode(writer, value.powerStatus, encoderContext)
writer.writeName("colorTemperature")
integerCodec.encode(writer, value.colorTemperature, encoderContext)
writer.writeEndDocument()
}
override def decode(reader: BsonReader,
decoderContext: DecoderContext): Monolight = {
var powerStatus: PowerStatus = PowerStatus.Off
var colorTemperature: Int = 0
reader.readStartDocument()
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
reader.readName() match {
case "powerStatus" =>
powerStatus = powerStatusCodec.decode(reader, decoderContext)
case "colorTemperature" =>
colorTemperature = integerCodec.decode(reader, decoderContext)
case "_id" =>
reader.readObjectId()
case _ =>
reader.skipValue()
}
}
reader.readEndDocument()
Monolight(powerStatus, colorTemperature)
}
override def getEncoderClass: Class[Monolight] = classOf[Monolight]
}

El siguiente ejemplo de código muestra cómo construir instancias Codec para los campos de la clase Monolight e implementar un CodecProvider personalizado:

class MonolightCodecProvider extends CodecProvider {
override def get[T](clazz: Class[T], registry: CodecRegistry): Codec[T] = {
if (clazz == classOf[Monolight]) {
new MonolightCodec(registry).asInstanceOf[Codec[T]]
} else {
null
}
}
}

El método get() devuelve un nuevo MonolightCodec cuando el driver solicita un Codec para la clase Monolight. El método pasa el CodecRegistry al constructor MonolightCodec para que el MonolightCodec pueda recuperar las instancias Codec de sus campos, como PowerStatusCodec y IntegerCodec. Si el driver solicita un Codec para cualquier otra clase, el método devuelve null.

Después de definir la lógica de conversión, puede realizar las siguientes operaciones:

  • Almacene datos de instancias de la clase Monolight en MongoDB

  • Recuperar datos de MongoDB en instancias de la clase Monolight

El siguiente ejemplo asigna la clase MonolightCodecProvider a la instancia MongoCollection pasándola al método withCodecRegistry(). A continuación, el ejemplo inserta una nueva instancia Monolight en la colección llamando al método insertOne() y, a continuación, llamando al método find() para devolver la instancia Monolight almacenada. El resultado muestra la instancia Monolight recuperada, lo que confirma que los códecs personalizados codificaron y descodificaron correctamente los datos.

object MonolightCodecExample {
def main(args: Array[String]): Unit = {
val uri = "<connection string URI>"
val mongoClient = MongoClient(uri)
val codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(
new IntegerCodec(), new PowerStatusCodec()
),
CodecRegistries.fromProviders(new MonolightCodecProvider()),
MongoClientSettings.getDefaultCodecRegistry()
)
val database = mongoClient.getDatabase("codecs_example_products")
val collection: MongoCollection[Monolight] = database
.getCollection[Monolight]("monolights")
.withCodecRegistry(codecRegistry)
val myMonolight = Monolight(PowerStatus.On, 5200)
Await.result(
collection.insertOne(myMonolight).toFuture(),
Duration.Inf
)
val lights = Await.result(
collection.find().toFuture(),
Duration.Inf
)
println(lights)
mongoClient.close()
}
}

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: