1. Sérialisation binaire en Java
La sérialisation binaire est le mécanisme standard de Java par lequel un objet est transformé en un flux d’octets de manière aussi compacte et rapide que possible. Pour cela, on utilise les classes ObjectOutputStream et ObjectInputStream. Le fichier obtenu est un ensemble d’octets qui n’est pas destiné à être lu par un humain.
On parle de « binaire » car tout est sérialisé à l’état « brut » : nombres, chaînes, tableaux, et même les références entre objets sont transformés en octets. C’est comme une valise bien rangée : efficace et rapide, mais sans mode d’emploi il n’est pas évident de savoir où se trouve quoi.
Comment cela fonctionne-t-il en Java ?
Supposons que nous ayons une classe User :
import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
// Constructeur, getters et setters
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Sérialisation vers un fichier binaire
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
User user = new User("John", 30);
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
System.out.println("L'objet User a été sérialisé dans le fichier user.bin");
} catch (Exception e) {
e.printStackTrace();
}
Désérialisation depuis un fichier binaire
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("Lu depuis le fichier : " + loadedUser.getName() + ", " + loadedUser.getAge());
} catch (Exception e) {
e.printStackTrace();
}
Attention : si vous ouvrez le fichier user.bin dans un éditeur de texte, vous verrez quelque chose comme : ¬í sr ... — c’est normal, c’est prévu !
Avantages de la sérialisation binaire
- Compacité et vitesse. L’écriture et la lecture sont aussi rapides que possible, sans « fioritures » inutiles.
- Tous les champs de l’objet sont conservés, y compris les objets imbriqués (s’ils sont également sérialisables via Serializable).
- Simple à utiliser pour un cache interne ou pour l’échange entre programmes Java.
Inconvénients
- Illisibilité. Un humain ne peut pas « jeter un coup d’œil » au contenu et le comprendre.
- Forte dépendance à la version de la classe. Une modification de la structure (ajout/suppression de champs) peut « casser » la lecture d’anciens fichiers.
- Problèmes de compatibilité entre différentes versions de Java et de la JVM.
- Ne convient pas aux échanges avec d’autres langages de programmation.
- Sécurité : la désérialisation de données provenant de sources non fiables est une voie directe vers des vulnérabilités.
2. Formats de sérialisation texte : JSON, XML et autres
La sérialisation binaire est adaptée à un usage interne, mais il faut souvent échanger des données entre différents langages (Java, JavaScript, Python) ou les stocker dans un format lisible — pratique pour les configurations, les journaux et les API. Pour cela, on utilise des formats texte : JSON, XML, YAML, CSV, etc.
JSON — le plus populaire
JSON (JavaScript Object Notation) est un format compact et lisible. Exemple d’un objet User sérialisé :
{
"name": "John",
"age": 30
}
En Java, on utilise le plus souvent des bibliothèques : Jackson (la plus populaire), Gson, ainsi que Moshi, JSON-B, etc.
XML — le vieil ami du développeur
XML (Extensible Markup Language) — plus « verbeux », mais formel et strict.
<User>
<name>John</name>
<age>30</age>
</User>
Pour XML en Java, on utilise souvent la bibliothèque standard JAXB (ou la plus ancienne XStream).
YAML, CSV et autres
- YAML — ressemble à JSON, mais est plus concis ; on l’emploie plus souvent pour des configurations que pour la sérialisation d’objets complexes.
- CSV — adapté aux tableaux « plats », mais peu adapté aux structures imbriquées.
- D’autres formats existent pour tous les goûts, mais en Java on utilise le plus souvent JSON et XML.
3. Comparaison des formats : quand utiliser quoi ?
| Format | Lisibilité | Compacité | Vitesse | Compatibilité | Quand l’utiliser |
|---|---|---|---|---|---|
| Binaire | Non | ++ | ++ | Java uniquement | Cache interne, sauvegarde rapide entre JVM |
| JSON | Oui | + | + | Tous langages | REST API, échange avec des services externes, configurations |
| XML | Oui | - | - | Tous langages | Intégration, schémas stricts, systèmes anciens |
- Binaire — à choisir pour un usage interne, lorsqu’il n’est pas nécessaire d’échanger avec des systèmes externes et que la performance maximale est importante.
- JSON — le meilleur choix pour l’échange avec des applications web, des clients mobiles et des REST API, ainsi que pour le stockage de paramètres.
- XML — utile lorsque des schémas stricts sont requis et pour l’intégration avec des solutions « d’entreprise ».
Important ! La sérialisation binaire ne convient qu’à l’échange de données entre programmes Java, et même dans ce cas il est plus sûr de l’utiliser entre programmes de la même version. Les formats texte comme JSON et XML sont plus universels : ils conviennent à l’échange de données entre différents langages et plateformes, rendant l’information lisible et portable.
4. Pratique : sérialisation en formats binaire et texte
Sérialisation binaire (ObjectOutputStream/ObjectInputStream)
Déjà vu plus haut, mais répétons pour consolider :
// Sérialisation
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
}
// Désérialisation
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
User loadedUser = (User) in.readObject();
}
Sérialisation en JSON avec Jackson (bref)
Pour utiliser Jackson, il faut ajouter ses bibliothèques au projet. Nous étudierons plus tard Maven et Gradle, mais pour l’instant vous pouvez ajouter les fichiers JAR manuellement. Exemple de dépendance pour Maven :
<!-- Maven -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
Exemple de sérialisation/désérialisation :
import com.fasterxml.jackson.databind.ObjectMapper;
User user = new User("John", 30);
ObjectMapper mapper = new ObjectMapper();
try {
// Sérialisation en chaîne
String json = mapper.writeValueAsString(user);
System.out.println(json); // {"name":"John","age":30}
// Sérialisation dans un fichier
mapper.writeValue(new File("user.json"), user);
// Désérialisation depuis la chaîne
User loadedUser = mapper.readValue(json, User.class);
// Désérialisation depuis le fichier
User loadedFromFile = mapper.readValue(new File("user.json"), User.class);
} catch (Exception e) {
e.printStackTrace();
}
Un fichier JSON peut être ouvert dans n’importe quel éditeur de texte, ce qui rend les données facilement lisibles et transportables entre différentes applications et différents langages.
5. Quel format utiliser et quand : conseils pratiques
- Mise en cache interne, fichiers temporaires, écriture/lecture rapides entre programmes Java : utilisez la sérialisation binaire standard. Mais souvenez-vous des problèmes de compatibilité entre versions !
- Échange avec des services externes, stockage de paramètres, intégration avec le front-end : utilisez JSON (Jackson, Gson).
- Intégration avec des systèmes « d’entreprise » nécessitant un schéma strict : XML (JAXB).
- Besoin que l’humain puisse ouvrir et lire le fichier : JSON ou XML, mais pas de format binaire.
6. Erreurs typiques lors de l’utilisation des formats de sérialisation
Erreur n° 1 : Tenter de sérialiser un objet contenant des champs non sérialisables. Si votre classe possède un champ qui n’implémente pas Serializable (par exemple, un flux ou une connexion à une base de données), la sérialisation binaire lèvera une erreur. Pour le JSON, c’est moins critique, mais avec des types « non standard » des problèmes peuvent également survenir.
Erreur n° 2 : Ouvrir un fichier binaire dans un éditeur de texte et s’en inquiéter. C’est normal ! Les fichiers binaires ne sont pas destinés à être lus par un humain.
Erreur n° 3 : Modifier la structure de la classe et ne plus pouvoir lire les anciens fichiers binaires. La sérialisation binaire est sensible aux modifications de la structure de la classe — une InvalidClassException survient souvent. En JSON/XML, c’est moins critique : les champs inconnus sont généralement ignorés ou reçoivent des valeurs par défaut.
Erreur n° 4 : Utiliser la sérialisation binaire pour échanger avec des systèmes externes. Cela ne fonctionnera pas : le format binaire n’est compris que par Java, et encore, si les versions correspondent.
Erreur n° 5 : Oublier d’ajouter les annotations nécessaires pour JSON/XML. Certaines bibliothèques exigent des annotations comme @JsonProperty, @XmlElement, sinon la sérialisation/désérialisation peut ne pas fonctionner comme prévu.
Erreur n° 6 : Ne pas vérifier que tous les objets imbriqués sont sérialisables. Pour la sérialisation binaire, c’est un problème courant ; pour le JSON aussi, si le modèle contient des types complexes.
GO TO FULL VERSION