1. Introduction
XML — abréviation de eXtensible Markup Language. Imaginez un JSON très strict et bavard, capable de répéter sans cesse «je suis structuré, crois-moi !». XML est un format texte où les données sont encadrées par des balises :
<Player>
<Name>Aragorn</Name>
<Health>100</Health>
</Player>
Pourquoi encore sérialiser des objets en XML de nos jours ?
- XML reste largement utilisé pour l'intégration entre de gros systèmes (souvent "legacy") où on a besoin non seulement de structure, mais aussi de validation selon des schémas stricts (XSD).
- XML est souvent utilisé dans des configurations d'entreprise (par exemple, App.config et Web.config dans les générations .NET plus anciennes).
- XML convient parfaitement aux cas où la capacité de la structure de données à s'auto-décrire est importante.
Fait intéressant : XML a été conçu pour être aussi «extensible» et validable que possible — d'où son nom. Il peut être vérifié par rapport à un schéma, ce que JSON n'offre pas «out of the box».
XmlSerializer : le héros
En .NET, la sérialisation des objets en XML est assurée par la classe System.Xml.Serialization.XmlSerializer.
- Il transforme les propriétés et champs publics d'un objet en éléments XML, et inversement : il reconstruit l'objet à partir du XML.
- Il ne fonctionne qu'avec des types et membres publics.
- Il ne sérialise pas les champs et propriétés privés — seulement ce qui est public !
- Il exige qu'il y ait un constructeur sans paramètres pour la classe sérialisable.
Attention : Si votre classe ne respecte pas ces exigences, XmlSerializer ne pourra pas fonctionner avec elle — il lèvera une exception lors de la sérialisation ou de la désérialisation.
2. Exemple simple — sérialiser un objet en XML
Prenons comme exemple la sérialisation de notre classe préférée Player en XML.
Étape 1. On décrit la classe
public class Player
{
public string Name { get; set; }
public int Health { get; set; }
public bool IsAlive { get; set; }
// Important : il faut un constructeur public sans paramètres !
public Player() { }
// Optionnel : pratique pour faciliter l'utilisation
public Player(string name, int health, bool isAlive)
{
Name = name;
Health = health;
IsAlive = isAlive;
}
}
Étape 2. On sérialise dans un fichier
using System.Xml.Serialization;
Player aragorn = new Player("Aragorn", 100, true);
// 1. On crée le XmlSerializer pour le type Player
XmlSerializer serializer = new XmlSerializer(typeof(Player));
// 2. On ouvre le fichier pour écrire (il sera créé s'il n'existe pas)
using FileStream fs = new FileStream("player.xml", FileMode.Create);
// 3. On sérialise l'objet en XML
serializer.Serialize(fs, aragorn);
Résultat (player.xml):
<?xml version="1.0"?>
<Player xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Aragorn</Name>
<Health>100</Health>
<IsAlive>true</IsAlive>
</Player>
Schéma visuel du processus le plus simple
Objet en mémoire ---> XmlSerializer.Serialize() ---> fichier XML sur le disque
3. Désérialisation — «on réanime» l'objet depuis le XML
Quand on a besoin de lire un objet précédemment sérialisé, le processus est l'inverse :
using FileStream fs = new FileStream("player.xml", FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(Player));
Player player = (Player)serializer.Deserialize(fs);
Console.WriteLine($"Nom: {player.Name}, Santé: {player.Health}, En vie: {player.IsAlive}");
Résultat : le programme affichera : Nom: Aragorn, Santé: 100, En vie: True
4. Sérialisation en chaîne — pas seulement dans un fichier
Sérialisation dans une chaîne
Parfois on ne veut pas écrire dans un fichier. Par exemple, on peut vouloir envoyer le XML sur le réseau ou l'afficher à l'écran.
using System.IO;
using System.Xml.Serialization;
Player player = new Player("Frodo", 42, true);
XmlSerializer serializer = new XmlSerializer(typeof(Player));
StringWriter stringWriter = new StringWriter();
serializer.Serialize(stringWriter, player);
string xmlString = stringWriter.ToString();
Console.WriteLine(xmlString); // Toute la chaîne XML — affichée à l'écran !
Désérialisation depuis une chaîne
De la même façon, on peut désérialiser un objet non pas depuis un fichier, mais depuis une chaîne :
string xml = "<Player Name=\"Frodo\"><HP>42</HP></Player>";
XmlSerializer serializer = new XmlSerializer(typeof(Player));
using StringReader stringReader = new StringReader(xml);
Player frodo = (Player)serializer.Deserialize(stringReader);
Console.WriteLine(frodo.Name); // Frodo
5. Personnaliser le XML : attributs pour contrôler la structure
Parfois le comportement par défaut ne vous convient pas. Le XML peut être trop verbeux ou les balises ne correspondent pas à ce qu'on veut. On utilise alors plusieurs attributs "magiques" qui indiquent au serializer comment représenter les membres de la classe.
Les plus utiles :
— donne le nom de l'élément.[XmlElement]
— transforme le champ en attribut XML plutôt qu'en élément.[XmlAttribute]
— exclut la propriété de la sérialisation.[XmlIgnore]
et[XmlArray]
— contrôlent l'enveloppe et les éléments des collections.[XmlArrayItem]
Exemple d'utilisation :
public class Player
{
[XmlAttribute]
public string Name { get; set; }
[XmlElement("HP")]
public int Health { get; set; }
[XmlIgnore]
public bool IsTempSessionPlayer { get; set; }
}
XML résultant :
<Player Name="Aragorn">
<HP>100</HP>
</Player>
Tableau des principaux attributs pour la sérialisation
| Attribut | Ce que ça influence | Exemple d'utilisation |
|---|---|---|
|
Transforme la propriété en un attribut XML | |
|
Change le nom de la balise | au lieu de |
|
Exclut complètement la propriété de la sérialisation | — |
|
Change le nom de l'enveloppe de la collection | |
|
Change le nom de l'élément de la collection | |
Exemple de sérialisation d'une collection complexe :
public class GameWorld
{
[XmlArray("Heroes")]
[XmlArrayItem("Hero")]
public List<Player> Players { get; set; } = new List<Player>();
}
XML :
<GameWorld>
<Heroes>
<Hero Name="Legolas">
<HP>90</HP>
</Hero>
<!-- ... -->
</Heroes>
</GameWorld>
On en reparlera dans les prochaines leçons ! :P
GO TO FULL VERSION