Comment générer des classes C# à partir d’un exemple JSON

Collez un exemple JSON — une réponse d’API, un fichier de configuration ou le corps d’un webhook — et cette page écrit les classes C# correspondantes : une classe par forme d’objet, avec des propriétés publiques et des accesseurs { get; set; }, le tout dans un seul fichier que vous pouvez copier. La conversion s’exécute dans votre navigateur, la charge utile n’est jamais envoyée et la page continue de fonctionner hors ligne une fois chargée.

Chaque nom de propriété est un identifiant C# valide : une clé qui entre en conflit avec un mot réservé devient un identifiant verbatim (@class), et une clé contenant des caractères que C# refuse est reconstruite tandis que la clé d’origine est conservée dans un attribut [JsonPropertyName], pour que System.Text.Json continue de mapper la charge utile. Les types, les noms de classe et l’imbrication sont déduits de l’exemple collé : le résultat est donc un brouillon à relire, pas un modèle terminé.

  1. Collez ou saisissez le JSON dans le champ ci-dessus. Les commentaires sont acceptés : une ligne // ou /* */ seule au-dessus d’une propriété devient une ligne /// <summary> dans la classe générée.
  2. Cliquez sur Générer des classes C#. Le fichier apparaît en dessous, coloré avec la grammaire C#, et le message au-dessus confirme l’exécution ou indique la ligne qui l’a interrompue.
  3. Cliquez sur Copier les classes C# pour placer le code sans couleurs dans le presse-papiers, puis collez-le dans un fichier .cs de votre projet.
  4. Modifiez le JSON et relancez la génération dès qu’une valeur vous semble fausse : le résultat précédent est effacé à chaque exécution, y compris en cas d’erreur, donc ce que vous copiez correspond toujours à l’entrée en cours.

Comment les valeurs, les clés et les tableaux deviennent du C#

Quel type C# reçoit chaque valeur JSON

Les nombres sont typés par plage : un entier qui tient dans Int32 devient int, un entier plus grand devient long jusqu’à 2^53, et tout ce qui a des décimales ou dépasse cette limite devient double ; 2147483648 et 1e10 ne finissent donc plus dans un int. true et false deviennent bool, et une valeur toujours null dans l’exemple devient string. Une chaîne reste string sauf si elle a la forme d’une date et peut être interprétée comme telle : 2024-05-06, 2024/05/06 10:00, 12/31/2024 et May 6, 2024 deviennent DateTime, alors que 20240506, 1-2, R2D2 et les identifiants numériques gardent leur texte exact.

Quand un même champ porte des types différents selon les éléments d’un tableau, le type numérique le plus large l’emporte (int avec long donne long, int avec 2.5 donne double) et tout autre désaccord devient object. Un champ null dans un élément et typé dans un autre prend le type de l’élément non nul : un seul null n’efface donc pas ce que montrent les autres lignes.

Comment une clé JSON devient une propriété C#

La propriété conserve la clé JSON partout où C# le permet. Une clé qui est un mot réservé s’écrit comme identifiant verbatim : class devient @class, qui compile et mappe toujours la clé du même nom. Une clé contenant des caractères refusés par C# est reconstruite : user-name devient userName, first name devient firstName, 1st devient _1st, a.b devient aB et une clé vide devient value. Deux clés qui aboutissent au même identifiant reçoivent un suffixe numérique au lieu de s’écraser, donc a.b et a&b donnent aB et aB2.

Dès qu’un nom de propriété diffère de la clé JSON, la propriété porte [JsonPropertyName("...")] et le fichier gagne un using System.Text.Json.Serialization ; l’attribut est omis quand il ne ferait que répéter le nom de la propriété, et une clé réservée comme class n’en a pas besoin puisque le nom verbatim correspond déjà. Cet attribut est la seule configuration écrite dans le fichier : aucune option de sérialiseur, aucun schéma, aucune annotation pour les clés inchangées.

Objets, tableaux et classes imbriquées

Chaque forme d’objet distincte devient une classe, nommée d’après sa clé JSON en PascalCase et jamais répétée dans le fichier : un second data devient Data2, un data imbriqué dans wrap devient WrapData, deux branches ne peuvent donc plus revendiquer Data. Une classe ne porte jamais le nom des types que le fichier utilise lui-même (List, String, Object, DateTime), car ce nom les masquerait, et un membre ne peut jamais répéter le nom de sa propre classe.

Les tableaux sont lus en entier, pas seulement via leur premier élément : [1, 2, 3] devient List<int>, [1, 2.5] devient List<double>, un tableau d’objets devient une liste d’une classe fusionnée contenant toutes les clés présentes dans n’importe quel élément, et un tableau mélangeant objets et scalaires devient List<object>. Un tableau vide devient List<string> à titre de valeur de remplacement. L’objet racine s’appelle toujours Root ; un tableau à la racine est signalé par un commentaire et modélisé à partir des éléments fusionnés, et une racine scalaire produit une classe vide avec un commentaire indiquant qu’aucune propriété n’a pu être déduite.

Ce qu’est le fichier généré, et ce qu’il n’est pas

La sortie est un unique fichier source C# : un commentaire de génération avec l’horodatage, les directives using dont le fichier a réellement besoin, puis les classes. C’est du C# simple, avec des propriétés { get; set; }, sans constructeur ni namespace : il s’intègre donc à tout projet à partir de .NET Core 3.0 ; rien ici ne le compile, la page ne fait qu’écrire le texte.

Les types proviennent du seul exemple collé : un champ toujours à 0 dans l’exemple est typé int même si la production envoie un décimal, et un tableau vide par hasard est typé List<string>. Traitez le résultat comme un brouillon : vérifiez les types sur lesquels vous vous appuyez, renommez la classe racine comme vous voulez et conservez les commentaires JSON de l’exemple, car ils sont la seule partie de l’entrée qui devienne de la documentation.

Outils récents :