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, puedes aprender acerca de Códecs y las clases de apoyo que gestionan la codificación y decodificación de objetos Java hacia y desde datos BSON en el driver Java Reactive Streams. La abstracción Codec te permite mapear cualquier tipo de Java a un tipo BSON correspondiente. Puedes usar esta abstracción para mapear tus objetos de dominio directamente hacia y desde BSON en lugar de usar un objeto intermedio basado en mapas como Document o BsonDocument.

Aprenda cómo especificar la lógica personalizada de codificación y decodificación utilizando la abstracción Codec en las siguientes secciones:

Para obtener información sobre cómo personalizar la lógica de codificación y decodificación para objetos Java simples y antiguos (POJO), consulte la guía Utilizar POJO para modelar los datos.

La interfaz Codec contiene métodos abstractos para serializar y deserializar objetos Java en datos BSON. Defina su lógica de conversión entre BSON y su objeto Java en su implementación de esta interfaz.

Para implementar la interfaz Codec, sobreescribe los métodos abstractos encode(), decode() y getEncoderClass().

El método encode() requiere los siguientes parámetros:

Parameter Type
Descripción

writer

Una instancia de una clase que implementa BsonWriter, un tipo de interfaz que expone métodos para guardar un documento BSON. Por ejemplo, la implementación de BsonBinaryWriter guarda en un flujo binario de datos. Utilice esta instancia para guardar su valor BSON mediante el método de guardar adecuado.

value

Los datos que tu implementación codifica. El tipo debe coincidir con la variable de tipo asignada a tu implementación.

encoderContext

Contiene metadatos sobre los datos del objeto Java que codifica en BSON, incluyendo si almacenar el valor actual en una colección de MongoDB.

Este método utiliza la instancia BsonWriter para enviar el valor codificado a MongoDB y no devuelve ningún valor.

El método decode() devuelve su instancia de objeto Java poblada con el valor de los datos BSON. Este método requiere los siguientes parámetros:

Parameter Type
Descripción

bsonReader

Una instancia de una clase que implementa BsonReader, un tipo de interfaz que expone métodos para leer un documento BSON. Por ejemplo, la implementación de BsonBinaryReader se lee de un flujo binario de datos.

decoderContext

Contiene información sobre los datos BSON que decodifica en un objeto Java.

El método getEncoderClass() devuelve una instancia de clase de la clase Java, ya que Java no puede inferir el tipo debido a la eliminación de tipos.

Los siguientes ejemplos de código muestran cómo implementar un Codec personalizado.

El enum ReadStatus contiene los valores READ y UNREAD para representar si se ha leído un libro.

public enum ReadStatus {
READ,
UNREAD
}

La clase ReadStatusCodec implementa Codec para convertir los valores Java enum en los correspondientes valores booleanos BSON. El método encode() convierte un ReadStatus a un booleano BSON y el método decode() realiza la conversión en la dirección opuesta.

public class ReadStatusCodec implements Codec<ReadStatus> {
@Override
public void encode(BsonWriter writer, ReadStatus value, EncoderContext encoderContext) {
writer.writeBoolean(value.equals(ReadStatus.READ) ? Boolean.TRUE : Boolean.FALSE);
}
@Override
public ReadStatus decode(BsonReader reader, DecoderContext decoderContext) {
return reader.readBoolean() ? ReadStatus.READ : ReadStatus.UNREAD;
}
@Override
public Class<ReadStatus> getEncoderClass() {
return ReadStatus.class;
}
}

Puede agregar una instancia del ReadStatusCodec a su CodecRegistry, que contiene una asignación entre su Codec y el tipo de objeto Realm Java al que se aplica. Continúe con la sección CodecRegistry de esta página para ver cómo incluir su Codec.

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 instancias de Codec que codifican y decodifican las clases Java que especifican. Puedes utilizar cualquiera de los siguientes métodos de fábrica estáticos de la clase CodecRegistries para construir un CodecRegistry a partir de las instancias de Codec contenidas en los tipos asociados:

  • fromCodecs()

  • fromProviders()

  • fromRegistries()

El siguiente snippet de código muestra cómo construir un CodecRegistry usando el método fromCodecs():

CodecRegistry codecRegistry = CodecRegistries.fromCodecs(new IntegerCodec(), new ReadStatusCodec());

En el ejemplo anterior, CodecRegistry incluye las siguientes implementaciones Codec:

  • IntegerCodec, un Codec que convierte Integers y forma parte del paquete BSON.

  • ReadStatusCodec, nuestra muestra Codec que convierte los valores enum de Java en booleanos BSON.

Puede recuperar las instancias de Codec de la instancia CodecRegistry del ejemplo anterior utilizando el siguiente código:

Codec<ReadStatus> readStatusCodec = codecRegistry.get(ReadStatus.class);
Codec<Integer> integerCodec = codecRegistry.get(Integer.class);

Si intenta recuperar una instancia Codec para una clase que no está registrada, el método get() lanza un CodecConfigurationException.

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 CodecProvider es una interfaz que contiene métodos abstractos que crean instancias de Codec y las asignan a una instancia CodecRegistry. De manera similar al CodecRegistry, la biblioteca BSON utiliza las instancias de Codec recuperadas por el método get() para convertir entre los tipos de datos Java y BSON.

Sin embargo, si agrega una clase que contiene campos que requieren objetos Codec correspondientes, debe instanciar los objetos Codec para los campos de la clase antes de instanciar el Codec para la clase. Puede usar el parámetro CodecRegistry en el método get() para pasar cualquier instancia Codec de la que dependa el Codec.

El siguiente ejemplo de código muestra cómo implementar CodecProvider para pasar BookCodec cualquier instancia de Codec que necesite en una instancia de CodecRegistry, como el ReadStatusCodec del ejemplo anterior:

public class BookCodecProvider implements CodecProvider {
public BookCodecProvider() {}
@Override
@SuppressWarnings("unchecked")
public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) {
if (clazz == Book.class) {
return (Codec<T>) new BookCodec(registry);
}
// return null when not a provider for the requested class
return null;
}
}

Para ver un ejemplo ejecutable que demuestre operaciones de lectura y guardar utilizando estas Codec clases, consulta la sección Ejemplo de códec personalizado de esta guía.

Cuando trabaje con POJO, considere usar el PojoCodecProvider para minimizar la duplicación de código al convertir tipos de datos de uso común y personalizar su comportamiento. Consulte nuestra guía Usar POJO para modelar sus datos para obtener más información.

El registro de codecs por defecto es un conjunto de CodecProvider clases que especifican la conversión entre los tipos de Java y MongoDB comúnmente usados. El driver utiliza automáticamente el registro de codecs por defecto a menos que especifiques uno diferente.

Si debe anular el comportamiento de una o más clases Codec, pero mantener el comportamiento del registro de códecs por defecto para las demás clases, puede especificar todos los registros en orden de precedencia. Por ejemplo, para anular el comportamiento del proveedor por defecto de un Codec para tipos enumerados con su MyEnumCodec personalizado, agréguelo a la lista de registros antes del registro de códecs por defecto, como se muestra en el siguiente ejemplo:

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

Para más información sobre las clases e interfaces de esta sección, consulte las siguientes secciones de la documentación de la API:

La clase BsonTypeClassMap contiene una asignación recomendada entre BSON y Java types. Puede utilizar esta clase en su Codec o CodecProvider personalizada para ayudarle a gestionar a qué clases contenedoras que implementan Iterable o Map, tales como la clase Document, decodificar sus tipos BSON.

Puedes agregar o modificar la asignación BsonTypeClassMap por defecto pasando un Map que contenga nuevas entradas o reemplazos.

El siguiente código snippet muestra cómo recuperar el tipo de clase Java que corresponde al tipo BSON en la instancia por defecto de BsonTypeClassMap:

BsonTypeClassMap bsonTypeClassMap = new BsonTypeClassMap();
Class<?> clazz = bsonTypeClassMap.get(BsonType.ARRAY);
System.out.println("Java type: " + clazz.getName());

Este código genera lo siguiente:

Java type: java.util.List

Puedes modificar estas asignaciones en tu instancia especificando reemplazos en el constructor BsonTypeClassMap. El siguiente ejemplo muestra cómo reemplazar la asignación de ARRAY en tu instancia BsonTypeClassMap con la clase Set:

Map<BsonType, Class<?>> replacements = new HashMap<BsonType, Class<?>>();
replacements.put(BsonType.ARRAY, Set.class);
BsonTypeClassMap bsonTypeClassMap = new BsonTypeClassMap(replacements);
Class<?> clazz = bsonTypeClassMap.get(BsonType.ARRAY);
System.out.println("Java type: " + clazz.getName());

Este código genera lo siguiente:

Java type: java.util.Set

Para obtener una lista completa de las asignaciones por defecto, consulte la Documentación de la API de BsonTypeClassMap.

Tip

Para ver ejemplos de cómo la clase Document utiliza BsonTypeClassMap, consulte el código fuente del driver para las clases DocumentCodecProvider y DocumentCodec.

Esta sección muestra cómo implementar Codec y CodecProvider para definir la lógica de codificación y decodificación para una clase Java personalizada. También muestra cómo especificar y utilizar sus implementaciones personalizadas para realizar operaciones de inserción y recuperación.

El siguiente ejemplo define una clase personalizada llamada Book y sus campos para el almacenamiento y la recuperación en una colección de MongoDB:

public class Book {
private String title;
private ReadStatus readStatus = ReadStatus.UNREAD;
private Integer pageCount;
public Book() {}
// ...

Esta clase contiene los siguientes campos, cada uno de los cuales requiere un Codec:

  • title contiene un valor String para el cual el ejemplo utiliza el StringCodec incluido en la librería BSON.

  • readStatus describe si se ha leído un libro, para lo cual el ejemplo utiliza el ReadStatusCodec personalizado que convierte los valores de enumeración en booleanos BSON.

  • pageCount contiene un valor Integer para el cual el ejemplo utiliza el IntegerCodec incluido en la librería BSON.

El siguiente ejemplo de código muestra cómo implementar un Codec para la clase Book. Ten en cuenta que el constructor espera una instancia de CodecRegistry de la cual recupera las instancias de Codec que necesita para codificar y decodificar sus campos:

public class BookCodec implements Codec<Book> {
private Codec<String> stringCodec;
private Codec<ReadStatus> readStatusCodec;
private Codec<Integer> integerCodec;
public BookCodec(CodecRegistry registry) {
this.stringCodec = registry.get(String.class);
this.readStatusCodec = registry.get(ReadStatus.class);
this.integerCodec = registry.get(Integer.class);
}
// Defines an encode() method to convert Book field values to BSON values
@Override
public void encode(BsonWriter writer, Book value, EncoderContext encoderContext) {
writer.writeStartDocument();
writer.writeName("title");
stringCodec.encode(writer, value.getTitle(), encoderContext);
writer.writeName("readStatus");
readStatusCodec.encode(writer, value.getReadStatus(), encoderContext);
writer.writeName("pageCount");
integerCodec.encode(writer, value.getPageCount(), encoderContext);
writer.writeEndDocument();
}
// Defines a decode() method to convert BSON values to Book field values
@Override
public Book decode(BsonReader reader, DecoderContext decoderContext) {
Book book = new Book();
reader.readStartDocument();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
String fieldName = reader.readName();
if (fieldName.equals("title")) {
book.setTitle(stringCodec.decode(reader, decoderContext));
} else if (fieldName.equals("readStatus")) {
book.setReadStatus(readStatusCodec.decode(reader, decoderContext));
} else if (fieldName.equals("pageCount")) {
book.setPageCount(integerCodec.decode(reader, decoderContext));
} else if (fieldName.equals("_id")) {
reader.readObjectId();
} else {
reader.skipValue();
}
}
reader.readEndDocument();
return book;
}
// Returns an instance of the Book class, since Java cannot infer the class type
@Override
public Class<Book> getEncoderClass() {
return Book.class;
}
}

Para que las instancias de Codec de los campos estén disponibles para Book, implemente un CodecProvider personalizado que se muestra en el siguiente ejemplo de código:

public class BookCodecProvider implements CodecProvider {
public BookCodecProvider() {}
@Override
@SuppressWarnings("unchecked")
public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) {
if (clazz == Book.class) {
return (Codec<T>) new BookCodec(registry);
}
// return null when not a provider for the requested class
return null;
}
}

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

  • Almacena datos de instancias de Book en MongoDB

  • Recuperar datos de MongoDB en instancias de Book

La siguiente clase de ejemplo contiene código que asigna el BookCodecProvider a la instancia de MongoCollection pasándolo al método withCodecRegistry(). La clase de ejemplo también inserta y recupera datos utilizando la clase Book y los códecs asociados:

public class BookCodecExample {
public static void main(String[] args) {
String uri = "<MongoDB connection URI>";
try (MongoClient mongoClient = MongoClients.create(uri)) {
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(new ReadStatusCodec()),
CodecRegistries.fromProviders(new BookCodecProvider()),
MongoClientSettings.getDefaultCodecRegistry());
MongoDatabase database = mongoClient.getDatabase("codecs_example_db");
MongoCollection<Book> collection = database.getCollection("books", Book.class)
.withCodecRegistry(codecRegistry);
// construct and insert an instance of Book
Book myBook = new Book();
myBook.setTitle("The Hobbit");
myBook.setReadStatus(ReadStatus.READ);
myBook.setPageCount(310);
Mono.from(collection.insertOne(myBook)).block();
// retrieve one or more instances of Book
Flux.from(collection.find())
.doOnNext(System.out::println)
.blockLast();
}
}
}

Si ejecuta el ejemplo anterior, el resultado será similar al siguiente:

Book [title=The Hobbit, readStatus=READ, pageCount=310]

Para obtener más información sobre los métodos y clases mencionados en esta guía, consulta la siguiente Documentación de la API: