Depuis .NET 7, System.Text.Json propose une fonctionnalité puissante : la génération de code à la compilation pour accélérer la (dé)sérialisation JSON, particulièrement utile en AOT ou dans des applications sensibles à la performance (MAUI, Blazor, services micro).. Comment en tirer profit ?
En .NET 9, cette approche est encore plus mature. Voici comment en tirer le meilleur.
⚡ Pourquoi utiliser la génération de source JSON ?
- Évite la réflexion à l’exécution (incompatible avec AOT trimming)
- Meilleures performances (initialisation et runtime)
- Contrôle plus précis des modèles et des métadonnées
- Support complet des structures complexes et des enums
🧪 Déclaration d’un contexte JSON source-gen
- Créer un fichier SerializationContext.cs
[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(List<User>))]
public partial class AppJsonContext : JsonSerializerContext
{
}
- Activer la génération dans le projet
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Text.Json.Serialization" />
</ItemGroup>
📦 Utilisation dans le code
var json = JsonSerializer.Serialize(user, AppJsonContext.Default.User);
var obj = JsonSerializer.Deserialize<User>(json, AppJsonContext.Default.User);
🧱 Exemple complet
public record User(string Name, int Age);
[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(List<User>))]
public partial class AppJsonContext : JsonSerializerContext { }
// Dans votre code
var user = new User("Alice", 30);
string json = JsonSerializer.Serialize(user, AppJsonContext.Default.User);
Les types supportés doivent être connus à la compilation. Pas de type dynamique ou polymorphe ici.
🔧 Gestion des options (indentation, case, etc.)
[JsonSourceGenerationOptions(WriteIndented = true, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(User))]
public partial class AppJsonContext : JsonSerializerContext { }
⚠️ Limitations
- Incompatible avec les types dynamiques (object, ExpandoObject, etc.)
- Nécessite des modèles stables et connus à l’avance
- Pas de support natif pour la polymorphie complexe (contourner par des converters)
✅ Bonnes pratiques
- Grouper les modèles dans un seul contexte
- Nommer clairement les fichiers générés pour faciliter les diagnostics
- Utiliser un contexte par domaine fonctionnel si besoin
📊 Comparatif : System.Text.Json vs Newtonsoft.Json
|
Critère
|
System.Text.Json (source-gen)
|
Newtonsoft.Json
|
|
Performance
|
✅ Très rapide (AOT-compatible)
|
⚠️ Moins performant (réflexion)
|
|
Support AOT / trimming
|
✅ Oui
|
❌ Non
|
|
Types dynamiques
|
❌ Non (via converter seulement)
|
✅ Oui
|
|
Polymorphisme
|
⚠️ Limité (avec configuration)
|
✅ Avancé
|
|
Génération de code à la compile
|
✅ Oui
|
❌ Non
|
|
Personnalisation fine
|
✅ Attributs et converters
|
✅ Très flexible
|
|
Compatibilité historique
|
⚠️ Partielle
|
✅ Très large
|
Choisissez System.Text.Json pour des apps modernes, rapides et AOT ; préférez Newtonsoft.Json si vous avez besoin de compatibilité maximale ou de cas très dynamiques.
🔚 Conclusion
La source generation avec System.Text.Json en .NET 9 permet une sérialisation rapide, sûre et compatible AOT. Elle est idéale pour les apps MAUI, Blazor, ou les API microservices modernes.
Stay Tuned !