[new:15/01/2013]La sérialisation des données est à la programmation Objet ce que le jerrycan est à l’essence : si vous n’avez pas le premier vous ne pouvez pas transporter ni conserver le second. Or sérialiser n’est pas si simple, surtout lorsqu’on souhaite un format lisible et cross-plateforme. JSON est alors une alternative à considérer.
Pourquoi sérialiser ?
Les raisons sont infinies, mais le but général reste le même : transporter ou stocker l’état d’un objet (ou d’une grappe d’objets). C’est donc un processus qui s’entend forcément en deux étapes : la sérialisation proprement-dite et la désérialisation sans laquelle la première aurait autant d’intérêt qu’une boîte de conserve sans ouvre-boîte…
On sérialise les objets pour les transmettre à un service, on désérialise pour consommer ses objets via des services, on peut aussi se servir de la sérialisation comme d’un moyen pratique pour stocker l’état d’une page sous Windows Phone ou Windows 8 par exemple. En effet, une sérialisation de type chaîne (XML ou JSON) à l’avantage de n’être que du texte, un simple texte. Plus de références, de memory leaks, ou autres problèmes de ce type. Les objets ayant été sérialisés peuvent être supprimés de la mémoire, ils pourront être recréés plus tard. Réhydratés comme un potage instantané… De plus une chaîne de caractères cela se traite, se transmet, se stocke très facilement et cela supporte aussi avec un taux de réussite souvent impressionnant la compression (Zip par exemple).
Il existe donc des milliers de raisons de vouloir sérialiser des objets (ou de consommer des objets lyophilisés préalablement par une sérialisation).
Choisir le moteur de sérialisation
Une des forces du Framework .NET a été, dès le début, de proposer des moteurs de sérialisation efficace, à une époque où d’autres langages et environnement peinaient à le faire. La sérialisation binaire a petit à petit cédé la place à la sérialisation XML, format devenu incontournable avec l’avènement du Web et des Web services.
.NET s’acquitte toujours de cette tâche de façon efficace d’ailleurs.
Mais alors pourquoi aller chercher plus loin ?
D’une part parce que les modes changes sans véritable raison technique, ainsi JSON est un format plus “hype” que XML ces temps-ci. Vous allez me dire, “je m’en fiche”. Oui, bien sur. Moi aussi. Ma la question n’est pas là. Il se trouve qu’il existe donc de plus en plus de services qui fournissent leurs données en JSON et qu’il faut bien pouvoir les interpréter pour les consommer… Realpolitik.
D’autres facteurs méritent malgré tout d’être pris en compte : notamment les capacités du moteur de sérialisation lui-même. Car tous ne sont pas égaux ! Certains, comme ceux du Framework .NET refusent les références circulaires par exemple…
Je sais que dit comme ça, les références circulaires on peut penser ne jamais en faire, mais il existe des tas de situations très simples et légitimes qui pourtant peuvent en voir surgir. Et il n’est pas “normal” d’avoir à “bricoler” les propriétés d’un objet pour que la plateforme technique puisse fonctionner. A fortiori lorsqu’on vise du cross-plateforme où la solution peut avoir à être implémentée chaque fois de façon différente.
Bien entendu les différences ne s’arrêtent pas là, certains moteurs savent gérer la sérialisation et la désérialisation des types anonymes ou des types dynamiques, d’autres non. Et les nuances de ce genre ne manquent pas !
Mieux vaut donc choisir son moteur de sérialisation correctement.
Il existe ainsi de bonnes raisons d’avoir, à un moment ou un autre, besoin d’un autre moteur de sérialisation que celui offert par .NET.
JSON.NET
C’est le moteur de sérialisation JSON peut-être le plus utilisé sous .NET, la librairie est bien faite, performante (plus que .NET en JSON en tout cas) et totalement portable entre les différentes versions de .NET. Le projet est open source sur CodePlex (Json.net), il peut être téléchargé depuis ce dernier ou même installé dans un projet via NuGet.
Mais toutes ces raisons ne sont pas suffisante pour embarquer une librairie de plus dans une application. Il faut bien entendu que les services rendus permettent des choses dont l’application a besoin et que les moteurs offerts par .NET ne puissent pas faire.
Voici un petit récapitulatif des différences entre les différents moteurs .NET (info données par JSON.NET) :
|
Json.NET |
DataContractJsonSerializer |
JavaScriptSerializer |
Supporte JSON |
Oui |
Oui |
Oui |
Supporte BSON |
Oui |
Non |
Non |
Supporte les schémas JSON |
Oui |
Non |
Non |
Supporte .NET 2.0 |
Oui |
Non |
Non |
Supporte .NET 3.5 |
Oui |
Oui |
Oui |
Supporte .NET 4.0 |
Oui |
Oui |
Oui |
Supporte .NET 4.5 |
Oui |
Oui |
Oui |
Supporte Silverlight |
Oui |
Oui |
Non |
Supporte Windows Phone |
Oui |
Oui |
Non |
Supporte Windows 8 |
Oui |
Oui |
Non |
Supporte Portable Class Library |
Oui |
Oui |
Non |
Open Source |
Oui |
Non |
Non |
Licence MIT |
Oui |
Non |
Non |
LINQ to JSON |
Oui |
Non |
Non |
Thread Safe |
Oui |
Oui |
Oui |
Syntaxe JSON XPath-like |
Oui |
Non |
Non |
Support JSON Indenté |
Oui |
Non |
Non |
Sérialisation efficace des dictionnaires |
Oui |
Non |
Oui |
Sérialization des dictionnaires "nonsensical" |
Non |
Oui |
Non |
Déserialise les propriétés IList, IEnumerable, ICollection, IDictionary |
Oui |
Non |
Non |
Serialise les références circulaires |
Oui |
Non |
Non |
Supporte sérialisation par référence |
Oui |
Non |
Non |
Déserialise propriétés et collection polymorphiques |
Oui |
Oui |
Oui |
Sérialise et déserialise les arrays multidimentionelles |
Oui |
Non |
Non |
Supporte inclusion des noms de type |
Oui |
Oui |
Oui |
Personalisation globale du process de sérialisation |
Oui |
Oui |
Non |
Supporte l'exclusion des null en sérialisation |
Oui |
Non |
Non |
Supporte SerializationBinder |
Oui |
Non |
Non |
Sérialisation conditionnelle |
Oui |
Non |
Non |
Numéro de ligne dans les erreurs |
Oui |
Oui |
Non |
Conversion XML à JSON et JSON à XML |
Oui |
Non |
Non |
Validation de schéma JSON |
Oui |
Non |
Non |
Génération de schéma JSON pour les types .NET |
Oui |
Non |
Non |
Nom de propriétés en Camel case |
Oui |
Non |
Non |
Supporte les constructeurs hors celui par défaut |
Oui |
Non |
Non |
Gestion des erreurs de sérialisations |
Oui |
Non |
Non |
Supporte la mise à jour d'un objet existant |
Oui |
Non |
Non |
Sérialisation efficace des arrays en Base64 |
Oui |
Non |
Non |
Gère les NaN, Infinity, -Infinity et undefined |
Oui |
Non |
Non |
Gère les constructeurs JavaScript |
Oui |
Non |
Non |
Sérialise les objets dynamiques .NET 4.0 |
Oui |
Non |
Non |
Sérializes les objets ISerializable |
Oui |
Non |
Non |
Supporte la sérialisation des enum par leur valeur texte |
Oui |
Non |
Non |
Supporte la limite de récursion JSON |
Oui |
Oui |
Oui |
Personnalisation des noms de propriétés par Attribut |
Oui |
Oui |
Non |
Personnalisation de l'ordre des propriétés par Attribut |
Oui |
Oui |
Non |
Personnalisation des propriétés "required" par Attribut |
Oui |
Oui |
Non |
Supporte les dates ISO8601 |
Oui |
Non |
Non |
Supporte le constructeur de data JavaScript |
Oui |
Non |
Non |
Supporte les dates MS AJAX |
Oui |
Oui |
Oui |
Supporte les noms sans quote |
Oui |
Non |
Non |
Supporte JSON en mode "raw" |
Oui |
Non |
Non |
Supporte les commentaires (lecture/écriture) |
Oui |
Non |
Non |
Sérialise les type anonymes |
Oui |
Non |
Oui |
Déserialise les types anonymes |
Oui |
Non |
Non |
Sérialisation en mode Opt-in |
Oui |
Oui |
Non |
Sérialisation en mode Opt-out |
Oui |
Non |
Oui |
Sérialisation en mode champ |
Oui |
Oui |
Non |
Lecture/écriture efficace des streams JSON |
Oui |
Oui |
Non |
Contenu JSON avec simple ou double quote |
Oui |
Non |
Non |
Surcharge de la sérialisation d'un type |
Oui |
Non |
Oui |
Supporte OnDeserialized, OnSerializing, OnSerialized et OnDeserializing |
Oui |
Oui |
Non |
Supporte la sérialisation des champs privés |
Oui |
Oui |
Non |
Supporte l'attribut DataMember |
Oui |
Oui |
Non |
Supporte l'attribut MetdataType |
Oui |
Non |
Non |
Supporte l'attribut DefaultValue |
Oui |
Non |
Non |
Sérialise les DataSets et DataTables |
Oui |
Non |
Non |
Sérialise Entity Framework |
Oui |
Non |
Non |
Sérialise nHibernate |
Oui |
Non |
Non |
Désérialisation case-insensitive sur noms des propriétés |
Oui |
Non |
Non |
Trace |
Oui |
Oui |
Non |
Utiliser JSON.NET
Cette librairie est bien entendu documentée et son adoption assez large faitr qu’on trouve facilement des exemples sur Internet, je ne vais pas copier ici toutes ces informations auxquelles je renvoie le lecteur intéressé.
Juste pour l’exemple, un objet peut se sérialisé aussi simplement que cela :
var JSON = JsonConvert.SerializeObject( monObjet );
(le résultat JSON est une string)
La désérialisation n’est pas plus compliquée.
Ensuite on entre dans les méandres des attributs de personnalisation (changer le nom d’une propriété, imposer un ordre particulier, …) voire la surcharge complète du processus de sérialisation, tout cela peut emmener loin dans les arcanes de JSON.NET car la librairie supporte un haut degré de personnalisation justement.
Conclusion
La sérialisation tout le monde connaît et s’en sert soit épisodiquement, soit fréquemment, mais souvent sans trop se poser de questions.
En vous proposant de regarder de plus près JSON.NET c’est une réflexion plus vaste que j’espère susciter : une interrogation sur les besoins réels de vos applications en ce domaine et la prise de conscience que le moteur de sérialisation ne se choisit pas au hasard en prenant le premier qui est disponible…
{
“MotDeLaFin”: “Stay Tuned!”
}