CodeGym /Cursos /JAVA 25 SELF /Formatos de serialización estándar: binario y de texto

Formatos de serialización estándar: binario y de texto

JAVA 25 SELF
Nivel 42 , Lección 2
Disponible

1. Serialización binaria en Java

La serialización binaria es el mecanismo estándar de Java por el que un objeto se transforma en un flujo de bytes de forma lo más compacta y rápida posible. Para ello se usan las clases ObjectOutputStream y ObjectInputStream. El archivo resultante es un conjunto de bytes que no está pensado para ser leído por una persona.

Se llama binaria porque todo se serializa en «estado bruto»: números, cadenas, arrays e incluso las referencias entre objetos se convierten en bytes. Es como una maleta empaquetada a presión: eficiente y rápida, pero sin instrucciones no es obvio qué hay y dónde.

¿Cómo funciona en Java?

Supongamos que tenemos la clase User:

import java.io.Serializable;

public class User implements Serializable {
    private String name;
    private int age;

    // Constructor, getters y setters
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
}

Serialización a un archivo binario

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

User user = new User("Vasya", 30);

try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
    out.writeObject(user);
    System.out.println("El objeto User se ha serializado en el archivo user.bin");
} catch (Exception e) {
    e.printStackTrace();
}

Deserialización desde un archivo binario

import java.io.FileInputStream;
import java.io.ObjectInputStream;

try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
    User loadedUser = (User) in.readObject();
    System.out.println("Leído del archivo: " + loadedUser.getName() + ", " + loadedUser.getAge());
} catch (Exception e) {
    e.printStackTrace();
}

Atención: si abre el archivo user.bin en un editor de texto, verá algo como: ¬í sr ... — es normal, ¡así está diseñado!

Ventajas de la serialización binaria

  • Compacidad y velocidad. El guardado y la lectura se realizan lo más rápido posible, sin «adornos» innecesarios.
  • Se guardan todos los campos del objeto, incluidos los objetos anidados (si también son serializables mediante Serializable).
  • Fácil de usar para caché interno o para intercambio entre programas Java.

Desventajas

  • Ilegibilidad. Una persona no podrá «echar un vistazo» al contenido y entender qué hay dentro.
  • Fuerte acoplamiento a la versión de la clase. Cambiar la estructura (añadir/eliminar campos) puede «romper» la lectura de archivos antiguos.
  • Problemas de compatibilidad entre diferentes versiones de Java y la JVM.
  • No apto para el intercambio con otros lenguajes de programación.
  • Seguridad: deserializar datos de fuentes no fiables es un camino directo hacia vulnerabilidades.

2. Formatos de serialización de texto: JSON, XML y otros

La serialización binaria es buena para uso interno, pero a menudo hay que intercambiar datos entre distintos lenguajes (Java, JavaScript, Python) o almacenarlos en un formato legible, lo cual es práctico para configuraciones, logs y API. Para ello se emplean formatos de texto: JSON, XML, YAML, CSV, etc.

JSON: el más popular

JSON (JavaScript Object Notation) es un formato compacto y legible. Ejemplo de un objeto User serializado:

{
  "name": "Vasya",
  "age": 30
}

En Java, para trabajar con JSON se usan con más frecuencia las bibliotecas: Jackson (la más popular), Gson, y también Moshi, JSON-B, etc.

XML: el viejo amigo del programador

XML (Extensible Markup Language) es más «verboso», pero formal y estricto.

<User>
  <name>Vasya</name>
  <age>30</age>
</User>

Para XML en Java se suele usar la biblioteca estándar JAXB (o la más antigua XStream).

YAML, CSV y otros

  • YAML se parece a JSON, pero es más conciso; se usa más para configuraciones que para serializar objetos complejos.
  • CSV es bueno para tablas «planas», pero poco adecuado para estructuras anidadas.
  • Hay formatos para todos los gustos, pero en Java lo más habitual es usar JSON y XML.

3. Comparación de formatos: ¿cuándo usar cada uno?

Formato Legibilidad Compacidad Velocidad Compatibilidad Cuándo usarlo
Binario No ++ ++ Solo Java Caché interno, guardado rápido entre JVM
JSON + + Cualquier lenguaje REST API, intercambio con servicios externos, configuraciones
XML - - Cualquier lenguaje Integración, esquemas estrictos, sistemas heredados
  • Binario: elija este formato para uso interno cuando no se requiera intercambio con sistemas externos y la máxima performance sea importante.
  • JSON: la mejor opción para intercambio con aplicaciones web, clientes móviles y REST API, así como para almacenar configuraciones.
  • XML: necesario cuando hay esquemas estrictos e integración con soluciones «corporativas».

¡Importante! La serialización binaria es adecuada solo para transferir datos entre programas Java, y aun así es más seguro usarla entre programas de la misma versión. Los formatos de texto como JSON y XML son más universales: sirven para el intercambio de datos entre distintos lenguajes y plataformas, haciendo la información legible y portátil.

4. Práctica: serialización en formato binario y de texto

Serialización binaria (ObjectOutputStream/ObjectInputStream)

Ya lo vimos arriba, pero lo repetimos para afianzar:

// Serialización
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
    out.writeObject(user);
}

// Deserialización
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
    User loadedUser = (User) in.readObject();
}

Serialización a JSON con Jackson (breve)

Para trabajar con Jackson hay que añadir sus bibliotecas al proyecto. Más adelante estudiaremos Maven y Gradle, pero por ahora puede incluir los archivos JAR manualmente. Ejemplo de dependencia para Maven:

<!-- Maven -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.0</version>
</dependency>

Ejemplo de serialización/deserialización:

import com.fasterxml.jackson.databind.ObjectMapper;

User user = new User("Vasya", 30);
ObjectMapper mapper = new ObjectMapper();

try {
    // Serialización a cadena
    String json = mapper.writeValueAsString(user);
    System.out.println(json); // {"name":"Vasya","age":30}

    // Serialización a archivo
    mapper.writeValue(new File("user.json"), user);

    // Deserialización desde cadena
    User loadedUser = mapper.readValue(json, User.class);

    // Deserialización desde archivo
    User loadedFromFile = mapper.readValue(new File("user.json"), User.class);

} catch (Exception e) {
    e.printStackTrace();
}

El archivo JSON se puede abrir en cualquier editor de texto, lo que hace que los datos sean fácilmente legibles y portables entre distintas aplicaciones y lenguajes.

5. Cuándo usar cada formato: consejos prácticos

  • Caché interno, archivos temporales, escritura/lectura rápida entre programas Java: use la serialización binaria estándar. ¡Pero recuerde la compatibilidad de versiones!
  • Intercambio con servicios externos, almacenamiento de configuraciones, integración con el frontend: use JSON (Jackson, Gson).
  • Integración con sistemas «corporativos» donde se requiere un esquema estricto: XML (JAXB).
  • Necesita que una persona pueda abrir y leer el archivo: JSON o XML, pero no formato binario.

6. Errores típicos al trabajar con formatos de serialización

Error n.º 1: Intentar serializar un objeto con campos no serializables. Si su clase tiene un campo que no implementa Serializable (por ejemplo, un flujo o una conexión con la BD), la serialización binaria dará un error. Para JSON no es tan crítico, pero con tipos «no estándar» también puede haber problemas.

Error n.º 2: Abrir un archivo binario en un editor de texto y asustarse. ¡Es normal! Los archivos binarios no están pensados para ser leídos por personas.

Error n.º 3: Cambiar la estructura de la clase y que los archivos binarios antiguos dejen de leerse. La serialización binaria es sensible a los cambios en la estructura de la clase: a menudo aparece InvalidClassException. En JSON/XML es menos crítico: los campos desconocidos suelen ignorarse o reciben valores por defecto.

Error n.º 4: Usar la serialización binaria para el intercambio con sistemas externos. No funcionará: el formato binario solo lo entiende Java, y aun así cuando coinciden las versiones.

Error n.º 5: Olvidar añadir las anotaciones necesarias para JSON/XML. Algunas bibliotecas requieren anotaciones como @JsonProperty, @XmlElement; de lo contrario, la serialización/deserialización puede no funcionar como se espera.

Error n.º 6: No comprobar que todos los objetos anidados sean serializables. En la serialización binaria es un problema frecuente; en JSON también, si en el modelo aparecen tipos complejos.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION