Comment générer des classes Java à partir d'un exemple JSON

Collez un exemple JSON — réponse d'API, fichier de configuration ou corps de webhook — et la page écrit les classes Java correspondantes : une classe par fichier, avec des champs privés et leurs getters et setters. Indiquez le nom de la classe racine et le paquet, cliquez sur Générer un JavaBean, puis téléchargez tous les fichiers en un ZIP ou reprenez le code directement dans la page. La conversion s'exécute dans le navigateur, rien n'est envoyé à un serveur et la page fonctionne hors ligne une fois chargée.

Deux points de la sortie sont volontaires. Chaque nom de champ est un identificateur Java valide, et toute propriété renommée conserve son nom JSON d'origine dans une annotation Jackson @JsonProperty : la classe générée continue donc de mapper la charge utile dont elle vient. Le reste — types, noms de classes, imbrication — est déduit de l'exemple collé, et le résultat est un brouillon à relire plutôt qu'un modèle fini.

  1. Collez le JSON dans le champ du haut. Les classes sont reconstruites à chaque frappe, ce qui permet de voir le modèle évoluer pendant que vous modifiez l'exemple.
  2. Ajustez Classe et Paquet si les valeurs par défaut ne conviennent pas : Classe est le nom de la classe racine (RootBean) et Paquet la ligne package écrite dans chaque fichier (com.example.model). Les deux sont nettoyés automatiquement lorsqu'ils ne forment pas du Java valide.
  3. Cliquez sur Générer un JavaBean. Chaque classe apparaît dans son propre bloc avec l'étiquette Nom de la classe ; le premier bloc est la classe racine, les suivants sont les classes qu'elle référence.
  4. Cliquez sur Télécharger les sources Java pour obtenir un ZIP nommé kivtools-java-models.zip qui recrée les dossiers du paquet et contient un fichier .java par classe, ou sur Effacer la saisie pour vider le champ et le résultat.

Comment les valeurs, les noms et les tableaux deviennent du Java

Quel type Java reçoit chaque valeur JSON

Le texte devient String et true ou false devient boolean. Les entiers tenant sur 32 bits deviennent int ; les entiers plus grands deviennent long, et ceux qui dépassent la plage représentable exactement par JavaScript deviennent BigDecimal pour qu'aucun arrondi silencieux n'ait lieu. Les nombres à virgule deviennent double, et null devient String, car un null isolé ne porte aucune information de type.

Une chaîne qui ressemble à une date devient java.util.Date : 2024-05-06, 2024/05/06, 12/31/2024, May 6, 2024 et les horodatages ISO 8601 avec fuseau horaire optionnel en font partie. Les chiffres seuls non : 20240506, 2024 et « 1-2 » restent des String, pour qu'un identifiant, une année ou un numéro de version ne devienne pas une date par erreur.

Des noms JSON aux noms Java

Un nom de propriété déjà valide comme identifiant est conservé tel quel, casse comprise. Tout le reste passe en camelCase par découpage sur les caractères que Java refuse : user_name devient userName, a.b devient aB, user name devient userName. Un nom qui est un mot réservé de Java ou qui commence par un chiffre reçoit un souligné en tête : {"class": 1} produit donc le champ _class.

Les noms de classes suivent les mêmes règles et commencent par une majuscule. Deux garde-fous s'ajoutent. Une classe ne peut pas porter le nom d'un type utilisé dans son propre fichier, donc une propriété nommée list produit ListModel au lieu de masquer java.util.List. Et deux objets ne peuvent pas revendiquer le même nom de classe — le second est qualifié par son parent, ainsi wrap.data devient WrapData tandis que le data externe reste Data. Dans un même objet, user_name et userName entrent en collision et le second champ devient userName2. L'annotation est importée depuis com.fasterxml.jackson.annotation.JsonProperty, le paquet Jackson 2.

Objets, tableaux et modèles imbriqués

Un objet imbriqué devient une classe à part, nommée d'après la propriété qui le contient, et le champ pointe vers cette classe. Les tableaux deviennent des List<...> : un tableau de chaînes donne List<String>, un tableau d'objets donne List<Users> plus la classe Users, et un tableau imbriqué garde sa profondeur, donc [[1,2]] donne List<List<Integer>>. Les arguments de type sont toujours encapsulés — List<Integer> et jamais List<int> — car Java n'y accepte pas de primitif.

Dans un tableau d'objets, tous les éléments sont lus, pas seulement le premier : un champ présent dans quelques éléments est tout de même ajouté, les tableaux de ces objets sont fusionnés, et une propriété dont le type change d'un élément à l'autre devient Object. Un tableau vide n'apporte aucun type d'élément : son élément est typé String à titre de valeur provisoire. Un tableau au niveau racine est traité de la même façon : la classe racine est construite à partir des propriétés de tous ses éléments.

Ce que sont les fichiers générés, et ce qu'ils ne sont pas

Chaque fichier contient la ligne package, les imports réellement utilisés, un court en-tête Javadoc avec l'heure de génération et l'adresse de cette page, une classe publique et des champs privés avec un getter et un setter. Pas de Lombok, pas de builder, ni equals ni hashCode : la sortie est un JavaBean simple qui n'a besoin que du JDK et, lorsque des champs ont été renommés, des annotations Jackson dans le classpath.

Rien n'est compilé ni confronté à votre projet ici, et les types proviennent d'un seul exemple. Les champs optionnels, les null imbriqués ou une valeur qui change de type entre deux appels n'apparaissent pas dans cet exemple, et un nombre int aujourd'hui deviendra un champ primitif qu'il faudra peut-être encapsuler plus tard. Quelques centaines de kilo-octets se convertissent dans le navigateur en bien moins d'une seconde : une grosse réponse ne pose donc pas de problème, mais l'exemple reste un instantané, pas un schéma.

Outils récents :