CodeGym /Cursos /JAVA 25 SELF /Formatos padrão de serialização: binário e texto

Formatos padrão de serialização: binário e texto

JAVA 25 SELF
Nível 42 , Lição 2
Disponível

1. Serialização binária em Java

Serialização binária — é o mecanismo padrão do Java pelo qual um objeto é transformado em um fluxo de bytes de forma máxima e rapidamente. Para isso, utilizam-se as classes ObjectOutputStream e ObjectInputStream. O arquivo resultante é um conjunto de bytes que não é destinado à leitura humana.

Ela é chamada de binária porque tudo é serializado em formato “bruto”: números, strings, arrays e até referências entre objetos viram bytes. É como uma mala bem compactada: eficiente e rápida, mas sem instruções não é óbvio onde está cada coisa.

Como isso funciona em Java?

Suponha que temos a classe User:

import java.io.Serializable;

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

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

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

Serialização para arquivo binário

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("Objeto User serializado para o arquivo user.bin");
} catch (Exception e) {
    e.printStackTrace();
}

Desserialização de arquivo binário

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("Lido do arquivo: " + loadedUser.getName() + ", " + loadedUser.getAge());
} catch (Exception e) {
    e.printStackTrace();
}

Atenção: se você abrir o arquivo user.bin em um editor de texto, verá algo como: ¬í sr ... — isso é normal, é assim mesmo!

Vantagens da serialização binária

  • Compacidade e velocidade. A gravação e a leitura são realizadas o mais rápido possível, sem “enfeites” desnecessários.
  • Todos os campos do objeto são preservados, incluindo objetos aninhados (se eles também forem serializáveis via Serializable).
  • Fácil de usar para cache interno ou para transferência entre programas Java.

Desvantagens

  • Ilegibilidade. Uma pessoa não conseguirá “espiar” o conteúdo e entender o que há ali.
  • Vinculação rígida à versão da classe. Alterar a estrutura (adicionar/remover campos) pode “quebrar” a leitura de arquivos antigos.
  • Problemas de compatibilidade entre diferentes versões de Java e JVM.
  • Não é adequado para troca com outras linguagens de programação.
  • Segurança: desserializar dados de fontes não confiáveis é um caminho direto para vulnerabilidades.

2. Formatos de serialização em texto: JSON, XML e outros

A serialização binária é boa para uso interno, mas muitas vezes é preciso transmitir dados entre diferentes linguagens (Java, JavaScript, Python) ou armazená-los em formato legível — útil para configurações, logs e APIs. Para isso, usam-se formatos de texto: JSON, XML, YAML, CSV etc.

JSON — o mais popular

JSON (JavaScript Object Notation) — formato compacto e legível. Exemplo de objeto User serializado:

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

No Java, para trabalhar com JSON, as bibliotecas mais usadas são: Jackson (a mais popular), Gson, além de Moshi, JSON-B etc.

XML — o velho amigo do programador

XML (Extensible Markup Language) — mais “verboso”, porém formal e rigoroso.

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

Para XML no Java, costuma-se usar a biblioteca padrão JAXB (ou a mais antiga XStream).

YAML, CSV e outras

  • YAML — parecido com JSON, porém mais conciso; é mais usado para configs do que para serialização de objetos complexos.
  • CSV — bom para tabelas “planas”, mas pouco adequado para estruturas aninhadas.
  • Existem formatos para todos os gostos, mas no Java os mais usados são JSON e XML.

3. Comparação de formatos: quando usar o quê?

Formato Legibilidade Compacidade Velocidade Compatibilidade Quando usar
Binário Não ++ ++ Apenas Java Cache interno, salvamento rápido entre JVMs
JSON Sim + + Qualquer linguagem APIs REST, integração com serviços externos, configurações
XML Sim - - Qualquer linguagem Integração, esquemas rigorosos, sistemas legados
  • Binário — escolha para uso interno, quando não é necessária a troca com sistemas externos e a máxima performance é importante.
  • JSON — a melhor escolha para integração com aplicações web, clientes móveis e APIs REST, além de armazenamento de configurações.
  • XML — necessário em esquemas rigorosos e integração com soluções “corporativas”.

Importante! A serialização binária é apropriada apenas para transferência de dados entre programas Java e, mesmo assim, é mais seguro usá-la entre programas da mesma versão. Formatos de texto como JSON e XML são mais universais: adequados para troca de dados entre diferentes linguagens e plataformas, tornando a informação legível e portável.

4. Prática: serialização em formatos binário e de texto

Serialização binária (ObjectOutputStream/ObjectInputStream)

Já vimos acima, mas vamos repetir para fixar:

// Serialização
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
    out.writeObject(user);
}

// Desserialização
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
    User loadedUser = (User) in.readObject();
}

Serialização em JSON com Jackson (resumo)

Para trabalhar com Jackson, é preciso adicionar suas bibliotecas ao projeto. Vamos estudar Maven e Gradle mais adiante; por enquanto, é possível adicionar os JARs manualmente. Exemplo de dependência para o Maven:

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

Exemplo de serialização/desserialização:

import com.fasterxml.jackson.databind.ObjectMapper;

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

try {
    // Serialização para String
    String json = mapper.writeValueAsString(user);
    System.out.println(json); // {"name":"Vasya","age":30}

    // Serialização para arquivo
    mapper.writeValue(new File("user.json"), user);

    // Desserialização de String
    User loadedUser = mapper.readValue(json, User.class);

    // Desserialização de arquivo
    User loadedFromFile = mapper.readValue(new File("user.json"), User.class);

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

O arquivo JSON pode ser aberto em qualquer editor de texto, o que torna os dados fáceis de ler e portáveis entre diferentes aplicações e linguagens.

5. Quando usar cada formato: conselhos práticos

  • Cache interno, arquivos temporários, gravação/leitura rápidas entre programas Java: use a serialização binária padrão. Mas lembre-se da compatibilidade de versões!
  • Integração com serviços externos, armazenamento de configurações, integração com o front-end: use JSON (Jackson, Gson).
  • Integração com sistemas “corporativos” em que é necessário um esquema rigoroso: XML (JAXB).
  • É necessário que uma pessoa possa abrir e ler o arquivo: JSON ou XML, mas não o formato binário.

6. Erros comuns ao trabalhar com formatos de serialização

Erro nº 1: tentar serializar um objeto com campos não serializáveis. Se sua classe tiver um campo que não implementa Serializable (por exemplo, um stream ou uma conexão com o BD), a serialização binária lançará um erro. Para JSON isso não é tão crítico, mas com tipos “não padrão” também podem ocorrer problemas.

Erro nº 2: abrir um arquivo binário em um editor de texto e se assustar. Isso é normal! Arquivos binários não são destinados à leitura humana.

Erro nº 3: alterar a estrutura da classe e os arquivos binários antigos deixam de ser lidos. A serialização binária é sensível a mudanças na estrutura da classe — frequentemente ocorre InvalidClassException. Em JSON/XML, isso é menos crítico: campos desconhecidos geralmente são ignorados ou recebem valores padrão.

Erro nº 4: usar serialização binária para integração com sistemas externos. Isso não vai funcionar: o formato binário é entendido apenas pelo Java e, ainda assim, quando as versões coincidem.

Erro nº 5: esquecer de adicionar as anotações necessárias para JSON/XML. Algumas bibliotecas exigem anotações como @JsonProperty, @XmlElement; caso contrário, a serialização/desserialização pode não funcionar como o esperado.

Erro nº 6: não verificar se todos os objetos aninhados são serializáveis. Para a serialização binária, isso é um problema frequente; para JSON também, se o modelo tiver tipos complexos.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION