Voir le flux RSS

François DORIN

[Actualité] Sérialisation XML et dictionnaire

Noter ce billet
par , 06/07/2018 à 23h11 (1334 Affichages)
Bonjour à tous,

Petit billet rapide avant de partir en congés.

Je ne sais pas pour vous, mais il m'arrive fréquemment d'avoir une structure ou une classe, que je sérialise en XML ou en JSON. Et même souvent, dans le cas d'applications Web, je passe même de l'un à l'autre.

Une des difficultés que l'on peut rencontrer, c'est que la sérialisation XML s’accommode mal avec les données présentes dans un dictionnaire clé/valeur, où la clé est une chaîne de caractères. Chose pourtant très aisée dans d'autres formats comme le JSON.

Ce n'est pas impossible, bien entendu, mais cela nécessite une intervention. La plus classique, et sans doute la plus naturelle, est de gérer manuellement la sérialisation. Même si cette approche est tout à fait fonctionnelle, cela nécessite une intervention manuelle à chaque sérialisation/désérialisation, et requiert de mettre en place des méthodes qui devront obligatoirement être appelées.

La solution que je vous propose aujourd'hui est un peu différente. Il s'agit de modifier la classe à sérialiser, pour qu'elle gère elle-même la sérialisation.

Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 [XmlRoot("Personne")]
    public class Personne
    {
        public string Nom {get; set;}
        public string Prenom {get; set;}
        public string DateNaissance {get; set;}
 
        [XmlIgnore]
        public Dictionary<string, string> Adresses{ get; set; }
 
        [XmlArray("Adresses")]
        [XmlArrayItem("Adresse")]
        public KeyValueXml<string, string>[] AdressesXMLProxy
        {
            get
            {
                return this.Adresses.Select( x => new KeyValueXml<string, string>(x.Key, x.Value)).ToArray() ;
            }
            set
            {
                if (value != null)
                {
                    this.Adresses = new Dictionary<string, string>();
                    foreach (var pair in value)
                    {
                        this.Adresses[pair.Key] = pair.Value;
                    }
                }
                else
                {
                    this.Adresses = null;
                }
            }
        }        
 
        [Serializable]
        public struct KeyValueXml<TKey, TValue>
        {
            public KeyValueXml(TKey key, TValue value)
            {
                this.Key = key;
                this.Value = value;
            }
 
            public TKey Key { get; set; }
            public TValue Value { get; set; }
        }
    }

Ici, la propriété qui nous intéresse est la propriété Adresses.

Comme nous pouvons le remarquer, c'est une propriété du type Dictionary<string, string>. Malheureusement, ce type n'est pas sérialisable. Aussi, l'astuce consiste ici à le marquer comme non sérialisable via l'attribut [XmlIgnore]. Il ne reste alors qu'à définir une autre autre propriété, qui sera calculée à partir de la propriété Adresses, et nous nous arrangerons pour que celle-ci soit sérialisable.

En C#, un dictionnaire peut être vu comme un tableau de tuple clé/valeur. Un tableau est sérialisable. Il reste donc à s'assurer que le type utilisé pour représenter le tuple soit aussi sérialisable. Ici, il s'agit du type KeyValueXml. Un connaisseur aurait pu suggérer d'utiliser directement la structure KeyValuePair définie par le framework .NET. Malheureusement, ce n'est pas possible, car ce type étant immutable, il n'est pas désérialisable.

L'idée consiste donc à définir une propriété "proxy" dont le type sera un tableau de KeyValueXml. Cette propriété porte ici le nom de AdressesXMLProxy. Comme elle agit comme un proxy, elle ne stocke rien par elle-même. Elle est liée, aussi bien dans son getter que son setter à la propriété Adresses.

Combiné avec des attributs comme XmlArray, XmlArrayItem ou encore XmlAttribute, on peut alors définir de manière assez fine le résultat souhaité.

En espérant que cette astuce puisse vous servir un jour...

Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Viadeo Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Twitter Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Google Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Facebook Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Digg Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Delicious Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog MySpace Envoyer le billet « Sérialisation XML et dictionnaire » dans le blog Yahoo

Mis à jour 09/07/2018 à 21h00 par Malick

Catégories
DotNET , C#

Commentaires

  1. Avatar de tomlev
    • |
    • permalink
    J'avais parlé d'une approche similaire il y a quelques années
    https://tlevesque.developpez.com/dot...ization-2/#LII