1. Introduction
Newtonsoft.Json est un peu un dinosaure dans le bon sens du terme. Il a été le standard de facto pour travailler avec JSON dans l'écosystème .NET pendant des années, bien avant que System.Text.Json n'apparaisse. Des millions de projets, des milliers de bibliothèques et frameworks (même pas mal de parties d'ASP.NET Core jusqu'à récemment) ont utilisé Json.NET.
Ses points forts sont :
- Très riche en fonctionnalités et flexible : Json.NET propose une tonne de réglages, d'attributs et d'options pour personnaliser la sérialisation/désérialisation. Il sait faire des choses que System.Text.Json gère mal ou pas du tout.
- Tolérant vis‑à‑vis du JSON "imparfait" : les données venant de systèmes externes ne sont pas toujours propres — Json.NET est souvent plus indulgent et permet de désérialiser sans trop de douleur.
- Rétrocompatible : si un projet ou une bibliothèque dépend de Json.NET, savoir l'utiliser reste essentiel.
Évidemment, System.Text.Json est plus rapide et a été conçu pour les besoins modernes. Mais Newtonsoft.Json reste un outil puissant, surtout si tu as besoin de logique spécifique ou de flexibilité maximale.
Comment installer Newtonsoft.Json ?
Comme c'est une librairie externe, ajoute le paquet via NuGet :
- Ouvre le projet.
- Clic droit sur le projet dans Solution Explorer.
- Choisis "Manage NuGet Packages...".
- Dans la recherche, tape Newtonsoft.Json.
- Sélectionne le paquet et clique sur "Install".
Après l'installation tu auras la dépendance et tu pourras utiliser Json.NET !
Comparaison des capacités de Newtonsoft.Json et System.Text.Json
| Fonctionnalité | System.Text.Json | Newtonsoft.Json |
|---|---|---|
| Sérialisation/désérialisation simple | Oui | Oui |
| Support des attributs pour les propriétés | Partiel | Complet |
| Convertisseurs personnalisés | Oui | Oui |
| Prise en charge des champs privés | Non | Oui |
| Travail avec des structures dynamiques | Limitée | Oui |
| LINQ to JSON (JObject/JArray) | Non | Oui |
| Reference Loop Handling | Oui | Oui |
| Support de DataTable, DataSet et types complexes | Non | Oui |
| Performance | Meilleure | Bonne |
2. Exemple de sérialisation et désérialisation d'un objet simple
Prenons une structure de jeu récurrente qu'on réutilisera dans plusieurs leçons :
public class Player
{
public string Name { get; set; }
public int Health { get; set; }
public bool IsAlive { get; set; }
public List<string> Inventory { get; set; }
public Position Position { get; set; }
}
public class Position
{
public int X { get; set; }
public int Y { get; set; }
}
Maintenant on va sauvegarder un objet Player en JSON et le restaurer :
using Newtonsoft.Json;
Player player1 = new Player
{
Name = "Aragorn",
Health = 100,
IsAlive = true,
Inventory = new List<string> { "sword", "bow", "healing potion" },
Position = new Position { X = 10, Y = 25 }
};
// Sérialisation en chaîne JSON
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);
// Désérialisation en objet Player
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"Nom: {player2.Name}, santé: {player2.Health}");
C'est tout ? Oui, presque, mais ce n'est que la partie émergée de l'iceberg. Voyons ce qui rend Newtonsoft.Json plus intéressant et flexible que d'autres libs.
3. Formatage, réglages et options avancées
Quand tu sérialises un objet, tu peux produire soit une chaîne compacte, soit un JSON bien formaté. Le comportement est contrôlé par des paramètres et des settings.
Exemple : Différents styles de formatage
// JSON lisible et joliment indenté
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);
// JSON compact "minifié"
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);
Réglages de sérialisation
Si besoin, passe un JsonSerializerSettings pour un contrôle fin :
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore, // Ignorer les champs null
DefaultValueHandling = DefaultValueHandling.Ignore, // Ignorer les champs avec valeur par défaut
Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);
Tu as un contrôle maximal sur le format de sortie : tu veux sauter les champs vides — pas de souci. Tu veux sérialiser même les propriétés privées — configure le contract.
4. Contrôle des champs et propriétés avec des attributs
Newtonsoft.Json supporte un système puissant d'attributs qui ajustent la sérialisation directement dans la classe.
JsonProperty — Renommer les propriétés
Si le protocole JSON exige un autre nom de champ :
public class Player
{
[JsonProperty("player_name")]
public string Name { get; set; }
// ...
}
JSON résultant :
{ "player_name": "Aragorn", ... }
JsonIgnore — Ignorer une propriété
public class Player
{
[JsonIgnore]
public int Health { get; set; }
}
Maintenant la propriété Health disparaîtra lors de la sérialisation.
JsonConverter — Transformations personnalisées
Permet d'indiquer quel converter utiliser pour un champ donné.
public class Player
{
[JsonConverter(typeof(InventoryToStringConverter))]
public List<string> Inventory { get; set; }
}
(Plus de détails sur les converters — plus bas.)
5. Travail avec des objets imbriqués et des collections
Json.NET gère très bien les objets imbriqués, tableaux, collections et dictionnaires.
Exemple : Dictionnaires
public class GameStats
{
public Dictionary<string, int> Scores { get; set; }
}
GameStats stats = new GameStats
{
Scores = new Dictionary<string, int>
{
["Alice"] = 1023,
["Bob"] = 999
}
};
string statsJson = JsonConvert.SerializeObject(stats, Formatting.Indented);
Console.WriteLine(statsJson);
Le JSON ressemblera à ça :
{
"Scores": {
"Alice": 1023,
"Bob": 999
}
}
6. Structures complexes : références cycliques, Self-Referencing Objects
Parfois les objets se réfèrent les uns aux autres. Newtonsoft.Json supporte la sérialisation de telles structures via des réglages spécifiques.
Exemple : Gérer les références cycliques
public class Person
{
public string Name { get; set; }
public Person Parent { get; set; }
public List<Person> Children { get; set; }
}
// On configure la sérialisation pour les cycles
var settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore // ou .Serialize
};
Person p1 = new Person { Name = "Papa" };
Person p2 = new Person { Name = "Fils", Parent = p1 };
p1.Children = new List<Person> { p2 };
string json = JsonConvert.SerializeObject(p1, settings);
Console.WriteLine(json);
Par défaut, si tu laisses ReferenceLoopHandling = Error, tu obtiendras une exception. C'est une protection contre une sérialisation infinie accidentelle.
7. Travailler avec des structures dynamiques : JObject, JArray
Quand la structure JSON est inconnue à l'avance ou change à la volée, utilise des objets dynamiques sans typage strict au niveau C#.
Types principaux :
- JObject — représentation d'un objet JSON.
- JArray — représentation d'un tableau.
using Newtonsoft.Json.Linq;
// Conversion d'une chaîne en JObject
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);
Console.WriteLine((string)obj["name"]); // Aragorn
Console.WriteLine((int)obj["health"]); // 100
// Ajout dynamique de propriétés
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());
Itération sur un tableau
string jsonArr = @"['apple', 'banana', 'cherry']";
JArray array = JArray.Parse(jsonArr);
foreach (JToken item in array)
{
Console.WriteLine(item);
}
8. Support de la versioning et champs obligatoires
Le format JSON peut évoluer, des champs peuvent manquer. Utilise des attributs et des réglages :
- [JsonProperty(Required = Required.Always)] — exiger la présence du champ (sinon exception).
- [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — remplir la valeur par défaut si le champ est absent.
public class Player
{
[JsonProperty(Required = Required.Always)]
public string Name { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue(50)]
public int Health { get; set; }
}
9. Conversion des dates et formats temporels
Travailler avec des dates demande souvent un format explicite.
var dateSettings = new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd"
};
string json = JsonConvert.SerializeObject(DateTime.Now, dateSettings);
Console.WriteLine(json); // "2024-06-15"
Et inversement lors de la désérialisation :
string dateJson = "\"2024-06-15\""; // Attention : c'est une chaîne entre guillemets !
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
GO TO FULL VERSION