1. Serializzazione binaria in Java
La serializzazione binaria è il meccanismo standard di Java con cui un oggetto viene trasformato in un flusso di byte nel modo più compatto e veloce possibile. Per questo si usano le classi ObjectOutputStream e ObjectInputStream. Il file risultante è un insieme di byte che non è pensato per essere letto da esseri umani.
Si chiama binaria perché tutto viene serializzato in forma «grezza»: numeri, stringhe, array, persino i riferimenti tra oggetti diventano byte. È come una valigia ben stipata: efficiente e veloce, ma senza istruzioni non è evidente dove sia cosa.
Come funziona in Java?
Supponiamo di avere una classe User:
import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
// Costruttore, getter e setter
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Serializzazione in file 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("Oggetto User serializzato nel file user.bin");
} catch (Exception e) {
e.printStackTrace();
}
Deserializzazione da file 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("Letto dal file: " + loadedUser.getName() + ", " + loadedUser.getAge());
} catch (Exception e) {
e.printStackTrace();
}
Attenzione: se aprite il file user.bin in un editor di testo, vedrete qualcosa come: ¬í sr ... — è normale, è proprio così che deve essere!
Vantaggi della serializzazione binaria
- Compattezza e velocità. Salvataggio e lettura sono il più possibile rapidi, senza «fronzoli» superflui.
- Vengono salvati tutti i campi dell’oggetto, inclusi gli oggetti annidati (se anche loro sono serializzabili tramite Serializable).
- Semplice da usare per cache interne o per lo scambio tra programmi Java.
Svantaggi
- Illeggibilità. Una persona non potrà «sbirciare» il contenuto e capirne il significato.
- Forte dipendenza dalla versione della classe. Cambiare la struttura (aggiunta/rimozione di campi) può «rompere» la lettura dei file più vecchi.
- Problemi di compatibilità tra diverse versioni di Java e JVM.
- Non adatto allo scambio con altri linguaggi di programmazione.
- Sicurezza: la deserializzazione di dati da fonti non verificate è una via diretta alle vulnerabilità.
2. Formati di serializzazione testuali: JSON, XML e altri
La serializzazione binaria è ottima per l’uso interno, ma spesso serve trasferire dati tra diversi linguaggi (Java, JavaScript, Python) o conservarli in forma leggibile — comodo per configurazioni, log, API. A questo scopo si usano formati testuali: JSON, XML, YAML, CSV ecc.
JSON — il più popolare
JSON (JavaScript Object Notation) è un formato compatto e leggibile. Esempio di oggetto User serializzato:
{
"name": "Vasya",
"age": 30
}
In Java per lavorare con JSON si usano spesso librerie come: Jackson (la più diffusa), Gson, nonché Moshi, JSON-B ecc.
XML — il vecchio amico del programmatore
XML (Extensible Markup Language) è più «verboso», ma formale e rigoroso.
<User>
<name>Vasya</name>
<age>30</age>
</User>
Per XML in Java si utilizza spesso la libreria standard JAXB (o la più datata XStream).
YAML, CSV e altri
- YAML — simile a JSON, ma più conciso; più spesso usato per configurazioni che per la serializzazione di oggetti complessi.
- CSV — valido per tabelle «piatte», ma poco adatto a strutture annidate.
- Esistono formati per tutti i gusti, ma in Java si usano più spesso JSON e XML.
3. Confronto dei formati: quando usare cosa?
| Formato | Leggibilità | Compattezza | Velocità | Compatibilità | Quando usarlo |
|---|---|---|---|---|---|
| Binario | No | ++ | ++ | Solo Java | Cache interna, salvataggio rapido tra JVM |
| JSON | Sì | + | + | Qualsiasi linguaggio | REST API, integrazione con servizi esterni, config |
| XML | Sì | - | - | Qualsiasi linguaggio | Integrazione, schemi rigorosi, sistemi legacy |
- Binario — sceglietelo per uso interno, quando non è necessario lo scambio con sistemi esterni e serve la massima performance.
- JSON — la scelta migliore per lo scambio con applicazioni web, client mobile e REST API, nonché per la memorizzazione delle impostazioni.
- XML — utile quando servono schemi rigorosi e per l’integrazione con soluzioni «enterprise».
Importante! La serializzazione binaria è adatta solo al trasferimento di dati tra programmi Java e, anche in questo caso, è più sicuro usarla tra programmi della stessa versione. I formati testuali come JSON e XML sono più universali: si prestano allo scambio di dati tra linguaggi e piattaforme diversi, rendendo le informazioni leggibili e portabili.
4. Pratica: serializzazione in formato binario e testuale
Serializzazione binaria (ObjectOutputStream/ObjectInputStream)
L’abbiamo già visto sopra, ma ripetiamo per fissare i concetti:
// Serializzazione
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
}
// Deserializzazione
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
User loadedUser = (User) in.readObject();
}
Serializzazione in JSON con Jackson (breve)
Per lavorare con Jackson bisogna aggiungere le sue librerie al progetto. Più avanti studieremo Maven e Gradle; per ora si possono aggiungere i file JAR manualmente. Esempio di dipendenza per Maven:
<!-- Maven -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
Esempio di serializzazione/deserializzazione:
import com.fasterxml.jackson.databind.ObjectMapper;
User user = new User("Vasya", 30);
ObjectMapper mapper = new ObjectMapper();
try {
// Serializzazione in stringa
String json = mapper.writeValueAsString(user);
System.out.println(json); // {"name":"Vasya","age":30}
// Serializzazione in file
mapper.writeValue(new File("user.json"), user);
// Deserializzazione da stringa
User loadedUser = mapper.readValue(json, User.class);
// Deserializzazione da file
User loadedFromFile = mapper.readValue(new File("user.json"), User.class);
} catch (Exception e) {
e.printStackTrace();
}
Il file JSON può essere aperto in qualsiasi editor di testo, rendendo i dati facilmente leggibili e trasferibili tra applicazioni e linguaggi differenti.
5. Quando usare quale formato: consigli pratici
- Cache interna, file temporanei, scrittura/lettura rapida tra programmi Java: usate la serializzazione binaria standard. Ma ricordate la compatibilità tra versioni!
- Scambio con servizi esterni, memorizzazione delle impostazioni, integrazione con il frontend: usate JSON (Jackson, Gson).
- Integrazione con sistemi «enterprise» dove è richiesto uno schema rigoroso: XML (JAXB).
- Serve che una persona possa aprire e leggere il file: JSON o XML, non il formato binario.
6. Errori tipici nel lavoro con i formati di serializzazione
Errore n. 1: si tenta di serializzare un oggetto con campi non serializzabili. Se la vostra classe ha un campo che non implementa Serializable (ad esempio uno stream o una connessione al DB), la serializzazione binaria restituirà un errore. Per JSON non è così critico, ma anche con tipi «non standard» possono sorgere problemi.
Errore n. 2: si apre un file binario in un editor di testo e ci si spaventa. È normale! I file binari non sono destinati alla lettura da parte di persone.
Errore n. 3: si cambia la struttura della classe e i vecchi file binari smettono di essere letti. La serializzazione binaria è sensibile alle modifiche nella struttura della classe — spesso compare InvalidClassException. In JSON/XML è meno critico: i campi sconosciuti di solito vengono ignorati o ricevono valori predefiniti.
Errore n. 4: si usa la serializzazione binaria per lo scambio con sistemi esterni. Non funziona: il formato binario è compreso solo da Java, e per di più a parità di versione.
Errore n. 5: per JSON/XML ci si dimentica di aggiungere le annotazioni necessarie. Alcune librerie richiedono annotazioni come @JsonProperty, @XmlElement, altrimenti serializzazione/deserializzazione potrebbero non funzionare come previsto.
Errore n. 6: non si verifica che tutti gli oggetti annidati siano serializzabili. Per la serializzazione binaria è un problema frequente; per JSON può esserlo ugualmente se nel modello compaiono tipi complessi.
GO TO FULL VERSION