Comment ne pas sérialiser (avec grâce) les valeurs nulles en XML avec .NET ?

Slim Ayache
YounitedTech
Published in
4 min readDec 18, 2019

Introduction

Nous sommes fin 2019, et l’XML est toujours en vie ! Il s’est bien incrusté dans pas mal de systèmes, et quand on veut le dégager il sort les XSD pour se défendre. Et en finance, on l’aime bien.

Nous avons été amenés récemment au court d’un projet à échanger des fichiers XML avec un partenaire. Ces XML contenaient des champs optionnels nullables.

Il y a plusieurs façons de représenter et gérer un champ nullable en XML :

  • Avec une balise vide <field></field>
  • L’attribut nil <field xsi:nil="true”></field>: la plus rigoureuse sans doute, et esthétiquement la plus moche
  • Ne pas afficher l’élément, à la JSON

Nous avons adopté la plus triviale d’entre elles : ignorer ce champ (loin des yeux, loin du cœur !) tout en utilisant les librairies standard du framework .NET. C’est-à-dire en étant le plus fainéant possible et utiliser l’XmlSerializer. Et de n’ajouter aucun code supplémentaire à nos POCO à part les attributs XML. En bref, du code simple et le moins verbeux possible.

Pour cela, nous avons créé un petit bout de code générique qu’on va explorer ensemble dans cet article (vous aurez compris que nous n’avons pas trouvé une réponse toute prête de Jon Skeet sur Stack Overflow).

Mise en situation

Assez de bavardage, voici le code.

Un objet sérialisable simple, avec un type référence et une primitive nullable.

Et un code pour sérialiser l’objet.

Les résultat (sans surprises !) est le suivant.

Essayons maintenant de sérialiser un objet vide ( i.e new TermDeposit() )
Le résultat est le suivant :

- On ne retrouve pas InvestorName vu que c’est un type référence.
- PlacementAmount est sérialisé avec le standard XML, c’est à dire avec nil.

Regardons comment on peut se débarrasser avec élégance de l’élément nil.

Une des façons Classiques : ShouldSerialize

Il y a une façon connue pour ignorer des champs selon un certain critère : ShouldSerialize. Elle consiste à ajouter une méthode (magique) ShouldSerializeMyProp qui retourne un bool de la condition d’ignorer une propriété.

Vu qu‘on est gentils, on vous donne deux (très vieux) blog posts qui parlent de cela, et même un lien vers la documentation de WinForms (qui fait ça en cachette !)

Pourquoi ShouldSerialize n’est pas sympa

Ajouter des méthodes invoquées de façon magique n’est pas très cool, avouons-le. Personnellement je n’ai jamais été à l’aise avec du code non auto-généré qui dépend du nom d’une variable ou d’une méthode pour opérer.

Polluer aussi le POCO avec une méthode pour chaque propriété à ignorer n’est pas joli non plus. ça passe pour une variable ou deux, mais supposons qu’on a une tonne de POCO sous la main, ou pire encore, des classes dans du code qu’on ne peut modifier.

Rappelez vous du début de l’article : on veut être fainéants et efficaces.
C’est l’approche que nous allons maintenant décrire.

Utiliser XmlAttributeOverrides pour Ignorer dynamiquement des éléments

1- Utiliser la réflexion pour lister les propriétés Nullables

2- Préparer les éléments xml qui ont une valeur nulle

3- Créer les XmlAttributeOverrides pour les valeurs nulles

4- Injecter l’XmlAttributeOverrides dans l’XmlSerializer

Et voilà tout le code ensemble

Et Le résultat (tadaaa)

Ce qui est sympa avec les XmlAttributeOverrides

Dans cet article nous avons utilisé XmlAttributeOverrides pour “ignorer” des éléments de l’XML, mais rien ne nous empêche d’injecter d’autres attributs. Ainsi, cette méthode peut s’avérer utile pour d’autres scénarios que celui d’ignorer une propriété

Améliorer (encore et toujours)

La solution présentée est déjà assez générique (elle se shoote à la réflexion !). Mais (nous, ingénieurs, sommes payés pour ce “mais” ) il y a quelques améliorations qu’on peut faire pour rendre le tout encore plus sexy :

  • Nous n’avons pas besoin de découvrir à chaque fois les propriétés d’une classe donnée, c’est une information statique à sauvegarder dans un cache.
  • Nous pouvons créer une belle méthode d’extension pour l’XmlSerializer qui aura un effet magique sur l’utilisateur de la classe (il vous enverra une lettre d’amour si vous lui faites ça).
  • La méthode GetAttributeOverrides peut servir à d’autres fins qu’injecter l’attribute Ignore dans le code, elle peut donc être refactorisée pour devenir plus versatile.

--

--

Slim Ayache
YounitedTech

Software developer (and I like it). I Speak AR, FR, EN. Interests in photography, music, books and one billion other things.