CodeGym /Cours /C# SELF /Configuration de la sérialisation (

Configuration de la sérialisation ( JsonSerializerOptions)

C# SELF
Niveau 45 , Leçon 3
Disponible

1. Introduction

Tout va bien si vos besoins collent au comportement par défaut. Mais assez souvent le client (ou un backend tiers) exige un format strict : partout du camelCase, les dates en ISO 8601, omission des null, converters custom, et autres joies de l'intégration.

C'est là qu'entre en scène notre nouvel ami — la classe JsonSerializerOptions.

Si la sérialisation était une cuisine, cette classe, ce sont vos épices, casseroles et ingrédients secrets pour assaisonner la sérialisation à votre goût.

Comment utiliser JsonSerializerOptions

Pour customiser le processus de sérialisation ou de désérialisation, on passe simplement un objet de configuration aux méthodes du serializer :

using System.Text.Json;

var options = new JsonSerializerOptions
{
    // Ici seront vos réglages
};

string json = JsonSerializer.Serialize(myObject, options);
var obj = JsonSerializer.Deserialize<MyType>(json, options);

Ce pattern est omniprésent : vous créez un JsonSerializerOptions, vous le configurez (voir plus bas), et vous le passez aux méthodes du serializer Serialize/Deserialize.

Important : Le même objet JsonSerializerOptions peut (et devrait souvent) être réutilisé pour plusieurs sérialisations.

2. Réglages principaux de JsonSerializerOptions

Regardons les "boutons" et "switches" les plus utilisés de cette classe.

Formatage JSON — WriteIndented

Les lignes JSON compactes vous piquent les yeux ? Pas de souci — activez le joli formatage avec indentations !

var options = new JsonSerializerOptions
{
    WriteIndented = true // JSON lisible par un humain
};

var person = new Person { Name = "Anna", Age = 30 };
string json = JsonSerializer.Serialize(person, options);

Console.WriteLine(json);

Sortie :

{
  "Name": "Anna",
  "Age": 30
}

Sans WriteIndented = true vous auriez reçu le JSON en une ligne {"Name":"Anna","Age":30}. En production on utilise souvent du JSON "minifié" (moins lourd), et pour le debug / les logs on préfère le formaté.

Case-naming — PropertyNamingPolicy

Les API demandent souvent que les noms de propriétés soient en camelCase (par ex. firstName au lieu de FirstName). En .NET on nomme généralement les propriétés en PascalCase, et ici intervient la propriété PropertyNamingPolicy :

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

var person = new Person { Name = "Oleg", Age = 25 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json); // {"name":"Oleg","age":25}

Si jamais vous avez besoin d'un style perso (par ex. TOUT EN MAJUSCULES), vous pouvez implémenter votre propre JsonNamingPolicy. En général CamelCase suffit.

3. Ignorer des propriétés

Ignorer ou ne pas ignorer les valeurs nullDefaultIgnoreCondition

Parfois on veut que les champs à valeur vide (null) n'apparaissent pas du tout dans le JSON. Raison : JSON plus compact, ou le système externe n'aime pas les null.

Pour ça on utilise la propriété DefaultIgnoreCondition :

using System.Text.Json.Serialization;

var options = new JsonSerializerOptions
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

var person = new Person { Name = null, Age = 22 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json); // {"Age":22}

Si vous voulez ignorer non seulement les null mais aussi les valeurs par défaut (par ex. int=0), utilisez WhenWritingDefault :

options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;

Inclure les fields — IncludeFields et [JsonInclude]

Par défaut seules les propriétés publiques avec setter public sont sérialisées. Si vous voulez sérialiser aussi les fields, vous pouvez activer :

var options = new JsonSerializerOptions
{
    IncludeFields = true
};

Exemple de classe :

public class Item
{
    public string Name;
    public int Id { get; set; }
}

var item = new Item { Name = "Book", Id = 12 };
string json = JsonSerializer.Serialize(item, options);
// {"Name":"Book","Id":12}

Pour sérialiser des champs/propriétés privés vous pouvez utiliser l'attribut [JsonInclude], mais c'est le sujet d'une autre leçon.

4. Conversion des valeurs

Formatage des dates — Converters

Par défaut System.Text.Json sérialise les dates strictement en ISO 8601 (par ex. "2023-12-27T15:30:45.123Z"), ce qui est pratique la plupart du temps. Mais parfois le format date/heure doit être particulier.

Pour ça on branche des converters. Exemple basique :

using System.Text.Json;
using System.Text.Json.Serialization;

public class CustomDateTimeConverter : JsonConverter<DateTime>
{
    private string _format = "yyyyMMdd";

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var date = reader.GetString();
        return DateTime.ParseExact(date, _format, null);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString(_format));
    }
}

// On utilise le converter
var options = new JsonSerializerOptions();
options.Converters.Add(new CustomDateTimeConverter());

var dateObj = new { Date = new DateTime(2022, 1, 5) };
string json = JsonSerializer.Serialize(dateObj, options); // {"Date":"20220105"}

5. Petites astuces utiles

Ignorer la casse des noms de propriétés à la désérialisation — PropertyNameCaseInsensitive

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};

var json = "{\"name\":\"Vasya\",\"age\":33}";
var person = JsonSerializer.Deserialize<Person>(json, options);
// person.Name == "Vasya"

Contrôler la profondeur et le niveau maximal d'objets — MaxDepth

var options = new JsonSerializerOptions
{
    MaxDepth = 32 // Par défaut 64
};

Mais si vos objets peuvent être sans fin en profondeur — par ex. un arbre avec références parent/enfant — mieux vaut repenser le modèle.

Commentaires dans le JSON — ReadCommentHandling (désérialisation)

Le JSON n'accepte pas officiellement les commentaires, mais parfois on rencontre des fichiers "créatifs" avec des commentaires //.

var options = new JsonSerializerOptions
{
    ReadCommentHandling = JsonCommentHandling.Skip
};

string json = "{\n  \"Name\": \"Ivan\", // Nom d'utilisateur\n  \"Age\": 30\n}";
var person = JsonSerializer.Deserialize<Person>(json, options);

Support des caractères spéciaux — Encoder

Parfois il faut contrôler comment le serializer échappe les caractères (par ex. pour ne pas transformer la cyrillique en \uXXXX). Vous pouvez spécifier un encoder :

using System.Text.Encodings.Web;

var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};

À utiliser prudemment, sinon vos emojis/idéogrammes risquent de se transformer en séquences Unicode !

6. Erreurs typiques en configurant la sérialisation

Erreur n°1 : on oublie le setter public. Un champ ou une propriété n'est pas sérialisé parce qu'il n'a pas de setter public, ou qu'il est privé.

Erreur n°2 : mauvaise gestion de l'ignorance des null. Avec DefaultIgnoreCondition activé, les propriétés null ne seront pas dans le JSON, alors que vous ne vous y attendiez pas.

Erreur n°3 : format de date incorrect. La date est sérialisée différemment de ce qui est attendu — branchez un converter custom (JsonConverter).

Erreur n°4 : attendre un ordre fixe des propriétés. Le standard JSON ne garantit pas l'ordre des champs. Si l'API exige un ordre strict, il faudra soit changer le modèle, soit utiliser des bibliothèques externes.

Erreur n°5 : paramètres différents pour sérialisation et désérialisation. Si vous n'utilisez pas les mêmes JsonSerializerOptions pour l'écriture et la lecture du JSON, des erreurs peuvent survenir, par ex. sur la casse des noms ou les formats.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION