CodeGym /Cours /C# SELF /Plongeons dans Newtonsoft....

Plongeons dans Newtonsoft.Json

C# SELF
Niveau 47 , Leçon 2
Disponible

1. Introduction

Si vous commencez à découvrir la sérialisation en .NET, il est naturel de se demander : pourquoi une autre bibliothèque alors qu'il y a déjà System.Text.Json intégré ? La réponse est simple : Newtonsoft.Json est apparue plus tôt et s'est développée pendant des années pour rester l'outil le plus flexible pour le JSON en .NET.

Elle est devenue le standard de facto parce qu'elle prend en charge des scénarios complexes : contrats personnalisés, converters puissants, sérialisation de champs privés, LINQ pour JSON, objets dynamiques (JObject), gestion flexible des références cycliques et de nombreux formats de date/heure. Beaucoup de bibliothèques et d'API utilisent encore Json.NET "sous le capot".

Important : dans certains scénarios System.Text.Json intégré est encore derrière les capacités de Newtonsoft.Json, donc apprendre Json.NET reste pertinent.

Comment ajouter Newtonsoft.Json (Json.NET)

Installez le package via NuGet :

dotnet add package Newtonsoft.Json

Ajoutez l'espace de noms :

using Newtonsoft.Json;

2. Sérialisation avec Newtonsoft.Json

Prenons la classe classique Person :

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Sérialiser un objet en chaîne JSON

Person person = new Person { Name = "Ivan", Age = 30 };

// Sérialisation en JSON
string json = JsonConvert.SerializeObject(person);

Console.WriteLine(json);
// Sortie : {"Name":"Ivan","Age":30}

Désérialiser le JSON en objet

string json = "{\"Name\":\"Ivan\",\"Age\":30}";

Person person = JsonConvert.DeserializeObject<Person>(json);

Console.WriteLine($"{person.Name}, {person.Age}");
// Sortie : Ivan, 30

Que se passe-t-il "sous le capot" ?

Newtonsoft.Json parcourt toutes les propriétés publiques (public), les sérialise en JSON et écrit dans la chaîne. Lors de la désérialisation il fait correspondre les clés du JSON aux noms des propriétés et remplit l'objet.

3. Sérialisation des collections d'objets

Sérialisation des collections et des tableaux

Les collections fonctionnent "out of the box".

List<Person> people = new List<Person>
{
    new Person { Name = "Ivan", Age = 30 },
    new Person { Name = "Maria", Age = 25 }
};

string json = JsonConvert.SerializeObject(people);
// Sortie : [{"Name":"Ivan","Age":30},{"Name":"Maria","Age":25}]

List<Person> deserialized = JsonConvert.DeserializeObject<List<Person>>(json);
// Vous avez de nouveau une liste de Person !

Particularités pour les dictionnaires

var dict = new Dictionary<string, int>
{
    ["apple"] = 2,
    ["banana"] = 5
};

string json = JsonConvert.SerializeObject(dict);
// Sortie : {"apple":2,"banana":5}

var deserializedDict = JsonConvert.DeserializeObject<Dictionary<string,int>>(json);
// Tout fonctionne !

Si les clés ne sont pas des strings (par exemple Dictionary<int,string>), Json.NET convertira les clés en chaînes pendant la sérialisation et tentera de les reconvertir lors de la désérialisation. Pour des clés complexes (par ex. Guid) il est plus sûr d'utiliser Dictionary<string, TValue>.

4. Travailler avec des objets imbriqués et des hiérarchies

public class Order
{
    public int Id { get; set; }
    public Person Customer { get; set; }
    public List<Product> Products { get; set; }
}
public class Product
{
    public string Title { get; set; }
    public double Price { get; set; }
}
Order order = new Order
{
    Id = 123,
    Customer = new Person { Name = "Ivan", Age = 30 },
    Products = new List<Product>
    {
        new Product { Title = "Ordinateur portable", Price = 50000.0 },
        new Product { Title = "Souris", Price = 1500.0 }
    }
};

string json = JsonConvert.SerializeObject(order);

Console.WriteLine(json);

Résultat : les objets imbriqués seront correctement représentés dans la structure JSON.

5. Configuration de la sérialisation avec des attributs

Ignorer une propriété

public class Person
{
    public string Name { get; set; }

    [JsonIgnore]
    public int Age { get; set; }
}

Maintenant Age n'apparaîtra pas dans le JSON.

Renommer une propriété

public class Person
{
    [JsonProperty("full_name")]
    public string Name { get; set; }
}

Dans le JSON le nom sera "full_name".

6. Configuration avancée : JsonSerializerSettings

Formatage (JSON lisible, multi-lignes) :

string json = JsonConvert.SerializeObject(
    people,
    Formatting.Indented
);

Résultat :

[
  {
    "Name": "Ivan",
    "Age": 30
  },
  {
    "Name": "Maria",
    "Age": 25
  }
]

Paramètres souvent utilisés :

Propriété Description
NullValueHandling
Comment gérer les propriétés null (les ignorer ou écrire explicitement null)
DefaultValueHandling
Ignorer ou non les valeurs par défaut
ReferenceLoopHandling
Que faire avec les références cycliques
DateFormatString
Format de chaîne pour les dates et heures

Exemple pour ignorer les null :

string json = JsonConvert.SerializeObject(
    person,
    new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }
);

7. Travailler avec des structures JSON dynamiques : JObject, JArray, etc.

Quand la structure JSON est inconnue à l'avance, utilisez les types de Newtonsoft.Json.Linq :

using Newtonsoft.Json.Linq;

string json = @"{
    'Name': 'Ivan',
    'Age': 30,
    'Skills': ['C#', 'SQL', 'JSON']
}";

JObject obj = JObject.Parse(json);

Console.WriteLine(obj["Name"]);     // Ivan
Console.WriteLine(obj["Skills"][0]); // C#

Créer du JSON "à la volée" :

var jObj = new JObject
{
    ["Status"] = "Success",
    ["Result"] = new JArray("item1", "item2", "item3")
};

Console.WriteLine(jObj.ToString(Formatting.Indented));

JObject et JArray sont des représentations d'un objet JSON et d'un tableau, en pratique ce sont des collections pratiques.

8. Astuces utiles

Références cycliques

Newtonsoft.Json sait gérer ça de façon flexible :

var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

string json = JsonConvert.SerializeObject(obj, settings);

Ainsi les cycles seront ignorés. Pour préserver les références on peut utiliser ReferenceLoopHandling.Serialize avec [JsonObject(IsReference = true)].

Sérialisation d'objets anonymes et dynamiques

var anon = new { Foo = 42, Bar = "Hello" };
string json = JsonConvert.SerializeObject(anon);
// {"Foo":42,"Bar":"Hello"}

Validation et gestion des erreurs

try
{
    Person p = JsonConvert.DeserializeObject<Person>(brokenJson);
}
catch (JsonSerializationException ex)
{
    Console.WriteLine("Erreur lors de la désérialisation : " + ex.Message);
}

Comparaison Newtonsoft.Json vs System.Text.Json

Newtonsoft.Json (Json.NET) System.Text.Json (.NET)
Support .NET .NET Framework/Standard/6+ .NET Core 3.0+ / .NET 5/6/9
LINQ pour JSON (JObject/JArray) Oui Non
Configuration flexible Très importante Limitée
Attributs ([JsonProperty], ...) Oui Oui (partiellement, moins de possibilités)
Support des propriétés privées Oui Non
Vitesse Plus lent dans certains scénarios Plus rapide
Converters complexes Oui Oui (moins flexible pour l'instant)
Support DataTable, DataSet Oui Non
Documentation et exemples En abondance En croissance

9. Erreurs de débutant et pièges typiques

Erreur n°1 : les propriétés deviennent null après la désérialisation.
Souvent la propriété n'a pas de setter ou il manque un constructeur sans paramètres — le sérialiseur n'a rien pour remplir l'objet.

Erreur n°2 : incompatibilité des noms de propriétés entre le JSON et la classe.
Si dans le JSON le champ est "fullName", et dans la classe c'est FullName, utilisez [JsonProperty] ou configurez un ContractResolver pour faire correspondre les noms.

Erreur n°3 : la sérialisation fonctionne seulement avec les propriétés publiques par défaut.
Les champs/propriétés privés ne sont pas sérialisés sans config supplémentaire. Il faut des converters ou des resolvers/contracts spéciaux.

Erreur n°4 : les références cycliques provoquent un StackOverflowException.
Les références mutuelles d'objets bouclent la sérialisation sans configuration. Configurez la gestion des références (par ex. ReferenceLoopHandling) ou modifiez le modèle de données.

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