Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Du 22 au 24 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. C# 10 et Visual Studio Code
  3. Sérialisation
Extrait - C# 10 et Visual Studio Code Les fondamentaux du langage
Extraits du livre
C# 10 et Visual Studio Code Les fondamentaux du langage
2 avis
Revenir à la page d'achat du livre

Sérialisation

Sérialisation en C#

De nos jours, le langage C# est l’un des plus utilisés pour développer des applications web. Une des problématiques les plus souvent rencontrées lors de communications en programmation Web est d’arriver à transférer des objets vers et depuis une application. À cet effet, l’objet doit être transformé dans un format universel. Cette transformation s’appelle la sérialisation. Ce processus permet de récupérer l’objet représenté sous un format échangeable, ce format étant le plus souvent une forme textuelle.

Pour que les données puissent transiter, il faut utiliser un flux de données (appelé stream en anglais, d’où le nom de la classe de base en C# : Stream). Ces flux peuvent prendre plusieurs formes, comme par exemple un flux de données en mémoire (représenté par la classe MemoryStream en C#) ou encore un flux de données vers un fichier sur le disque (représenté par la classe FileStream en C#).

Il existe plusieurs façons de sérialiser un objet, et parmi celles-ci, on trouve les suivantes :

  • La sérialisation binaire, qui permet de représenter un objet sous un format binaire.

  • La sérialisation XML, qui transforme l’objet en chaîne de caractères au format XML....

Sérialisation binaire

L’approche binaire est le mode de sérialisation le plus simple à mettre en place. Il est également celui qui permet de stocker le plus d’informations sur le type de l’objet et qui possède la plus grande fiabilité de conversion des valeurs et types stockés. Néanmoins, son format est propriétaire : il n’est pas portable ni compatible avec d’autres langages et solutions, de sorte que son utilisation n’est à retenir que si l’émetteur et le destinataire sont tous deux des programmes en C#.

Avec l’arrivée de .NET 6 et de C# 10, il est fortement déconseillé d’utiliser ce mode de sérialisation. Les explications et le fonctionnement décrits dans cette section sont uniquement proposés à des fins de suivi, pour les lecteurs qui auraient besoin de faire la maintenance d’un système utilisant ce système de sérialisation. L’utilisation des objets vus dans cette section est déconseillée pour de nouvelles applications, car ils sont marqués comme obsolètes en .NET 6 et seront supprimés en .NET 7.

Deux approches permettent d’activer la sérialisation binaire :

  • En utilisant les attributs appropriés sur un type donné.

  • En implémentant l’interface ISerializable.

Les attributs sont plus faciles et rapides à mettre en place, mais moins flexibles que l’implémentation de l’interface ISerializable. Il convient de retenir la solution à préférer en fonction de l’objectif.

1. Utilisation des attributs

Cette approche est la plus simple et rapide à mettre en place. En considérant la classe suivante, il suffit d’ajouter l’attribut [Serializable] au-dessus de la déclaration de la classe :

[Serializable] 
public class Personne 
{ 
    public string Nom { get; set; } 
    public string Prenom { get; set; } 
} 

Ce faisant, dès lors qu’on demandera de sérialiser une variable de type Personne, le serializer sera informé, grâce à la présence de l’attribut, qu’il doit considérer la sérialisation de chaque donnée...

Sérialisation XML

Contrairement à l’approche binaire, la sérialisation en XML repose sur un format reconnu comme un standard dans l’industrie. Longtemps utilisé, le XML est un langage de balisage assez verbeux, mais de fait assez puissant et extensible. De nos jours, il est encore utilisé, notamment dans l’approche de fichiers de configuration ou encore de messages d’échanges pour les services utilisant le protocole SOAP.

.NET offre deux façons de gérer la sérialisation, que nous allons couvrir dans cette section. Nous allons commencer par l’approche bas niveau, plus performante, mais également plus contraignante.

1. XmlSerializer

La classe XmlSerializer, qui se trouve dans le namespace System.Xml.Serialization, permet d’effectuer la sérialisation et la désérialisation d’objets en XML. Le fonctionnement ressemble à celui du BinaryFormatter, c’est-à-dire qu’il faut fournir un objet ainsi qu’un stream. La seule différence notable entre les deux est qu’il est nécessaire de spécifier le type à gérer lors de la création de l’instance de la classe XmlSerializer, en utilisant le mot-clé typeof :

var p = new PersonneXml { Nom = "Mommer", Prenom = "Christophe" }; 
  
var serializer = new XmlSerializer(typeof(PersonneXml)); 
 
using (var stream = new FileStream("person.xml", FileMode.Create)) 
{ 
    serializer.Serialize(stream, p); 
} 
using (var stream = new FileStream("person.xml", FileMode.Open)) 
{ 
    var p2 = (PersonneXml)serializer.Deserialize(stream); 
    System.Console.WriteLine("Bonjour " + p2.Nom + " " + p2.Prenom); 
} 

La sérialisation avec cette approche repose sur l’utilisation d’attributs permettant de dire ce que l’on souhaite sérialiser ou non, et comment la sérialisation doit s’effectuer.

Pour rappel, le format XML repose sur des éléments qui peuvent avoir un contenu mais également des attributs. Il est possible de personnaliser la sortie avec les attributs [XmlElement] et [XmlAttribute]. Ces derniers peuvent prendre en paramètre...

Sérialisation JSON

Le format de données JSON est de nos jours le plus utilisé pour échanger des informations, du fait de sa simplicité mais également de sa légèreté syntaxique par rapport au XML. De ce fait, le framework .NET permet de traiter nativement le format JSON.

Depuis le framework .NET Core 3, les ingénieurs de Microsoft ont ajouté directement dans le framework une nouvelle façon de traiter les flux JSON, plus performante que l’approche précédente, et ce afin de ne plus dépendre du package communautaire le plus largement utilisé jusqu’alors : NewtonSoft.Json.

À l’instar de l’API fournie pour le traitement XML, il existe deux approches pour traiter le JSON :

  • De façon procédurale, en lisant le flux de bout en bout à l’aide d’un curseur grâce aux classes Utf8JsonReader et Utf8JsonWriter.

  • Avec une approche orientée document, à l’instar de XDocument, grâce à la classe JsonDocument.

1. Utf8JsonReader et Utf8JsonWriter

Le format JSON est relativement simple car le type de données rencontré lors de la lecture d’un flux JSON est forcément contenu dans la liste suivante :

  • Début ou fin d’objet

  • Début ou fin de tableau

  • Nom de propriété

  • Valeur (chaîne de caractères, numérique ou booléenne)

De ce fait, l’approche tenue dans la classe Utf8JsonReader se focalise sur la lecture des données une par une, et c’est le rôle du développeur de définir ce qu’il souhaite réaliser.

Considérons le flux JSON suivant :

var json = @"{ 
  ""Prenom"" : ""Christophe"", 
  ""Nom"" : ""Mommer"", 
  ""Age"" : 33, 
  ""Adresse"" : { 
    ""Rue"": ""Place de la comédie"", 
    ""Ville"" : ""Montpellier"" 
  } 
}"; 

Lorsqu’on utilise le caractère @ devant une chaîne de caractères, l’utilisation...

Exercice

Le but de cet exercice est de mettre en pratique les différentes formes de sérialisation vues dans cet ouvrage, en lecture comme en écriture.

1. Énoncé

La base de travail est le projet développé au chapitre Programmation orientée objet et au chapitre Algorithmique, à savoir le jeu pour deviner le nombre mystère. Il s’agit de créer ici un tableau de scores qui s’affichera sous le menu du jeu, en proposant au joueur de rentrer son nom s’il entre au palmarès des cinq meilleurs joueurs.

Pour ce faire, on calcule un nombre de points correspondant à la formule suivante : nombre de possibilités + (nombre d’essais restant à la puissance difficulté). 

Par exemple, si un joueur a tenté de deviner un nombre entre 1 et 100, il y a 100 possibilités. S’il a choisi de jouer en facile, le niveau de difficulté est de 1. Il faut donc mettre le nombre d’essais restants en puissance de ce nombre. Si le joueur a gagné en 4 coups, il lui reste donc 6 manches, ce qui donne 100 + 6 puissance 1 = 106 points.

L’opérateur C# à utiliser pour faire une puissance est ^. Ainsi, pour stocker dans une variable 2 puissance 3, on écrit var i = 2 ^ 3;.

Il faut donc lire le tableau des scores et voir si le joueur peut entrer au palmarès. Si c’est le cas, on demande la saisie de son nom afin de l’inscrire à la bonne position.

Il n’y a pas de contraintes particulières...