Java-Klassen aus einem JSON-Beispiel erzeugen

JSON-Beispiel einfügen — eine API-Antwort, eine Konfigurationsdatei oder ein Webhook-Body — und die Seite schreibt die passenden Java-Klassen: eine Klasse pro Datei, mit privaten Feldern sowie je einem Getter und Setter. Wurzelklasse und Paket festlegen, auf JavaBean erzeugen drücken und alle Dateien anschließend als ein ZIP herunterladen oder den Code direkt aus der Seite übernehmen. Die Umwandlung läuft im Browser, die Daten werden nicht hochgeladen, und nach dem Laden arbeitet die Seite auch offline weiter.

Zwei Punkte der Ausgabe sind Absicht. Jeder Feldname ist ein gültiger Java-Bezeichner, und jede umbenannte Eigenschaft behält ihren ursprünglichen JSON-Namen in einer Jackson-Annotation @JsonProperty — die erzeugte Klasse bildet die eingefügte Nutzlast also weiterhin ab. Alles andere, also Typen, Klassennamen und Verschachtelung, wird aus dem Beispiel abgeleitet; das Ergebnis ist deshalb ein Entwurf zum Prüfen und kein fertiges Modell.

  1. JSON oben in das Feld einfügen. Die Klassen werden bei jedem Tastendruck neu aufgebaut, sodass sich das Modell beim Bearbeiten des Beispiels mitverändert.
  2. Klasse und Paket anpassen, falls die Vorgaben nicht passen: Klasse ist der Name der Wurzelklasse (RootBean), Paket ist die Zeile package in jeder Datei (com.example.model). Beide werden automatisch bereinigt, wenn sie kein gültiges Java ergeben.
  3. Auf JavaBean erzeugen drücken. Jede Klasse erscheint in einem eigenen Block mit der Beschriftung Klassenname; der erste Block ist die Wurzelklasse, die weiteren sind die Klassen, auf die sie verweist.
  4. Über Java-Quellcode herunterladen kommt ein ZIP namens kivtools-java-models.zip, das die Paketordner nachbildet und eine .java-Datei pro Klasse enthält; Eingabe leeren räumt Feld und Ergebnis.

Wie Werte, Namen und Arrays zu Java werden

Welcher Java-Typ aus welchem JSON-Wert wird

Text wird zu String, true oder false wird zu boolean. Ganze Zahlen, die in 32 Bit passen, werden int; größere ganze Zahlen werden long, und ganze Zahlen außerhalb des Bereichs, den JavaScript exakt darstellt, werden BigDecimal, damit nichts unbemerkt gerundet wird. Zahlen mit Dezimalpunkt werden double, und null wird String, weil ein einzelnes null keine Typinformation trägt.

Eine Zeichenkette, die wie ein Datum aussieht, wird java.util.Date. 2024-05-06, 2024/05/06, 12/31/2024, May 6, 2024 und ISO-8601-Zeitstempel mit optionaler Zeitzone zählen dazu. Reine Ziffernfolgen nicht: 20240506, 2024 und "1-2" bleiben String, damit aus einer ID, einem Jahr oder einer Versionsnummer nicht versehentlich ein Datum wird.

Wie aus JSON-Namen Java-Namen werden

Ein Eigenschaftsname, der bereits ein gültiger Java-Bezeichner ist, bleibt wie geschrieben — samt Groß- und Kleinschreibung. Alles andere wird auf camelCase gebracht, indem an den Zeichen getrennt wird, die Java nicht erlaubt: user_name wird zu userName, a.b zu aB, user name zu userName. Ein Name, der ein Java-Schlüsselwort ist oder mit einer Ziffer beginnt, bekommt einen Unterstrich vorangestellt; {"class": 1} ergibt also das Feld _class.

Klassennamen folgen denselben Regeln und beginnen groß. Zwei zusätzliche Absicherungen greifen. Eine Klasse darf nicht wie ein Typ heißen, den dieselbe Datei verwendet, deshalb ergibt eine Eigenschaft namens list die Klasse ListModel statt einer Verdeckung von java.util.List. Und zwei Objekte dürfen nicht denselben Klassennamen beanspruchen — das zweite wird mit seinem Elternteil qualifiziert, aus wrap.data wird WrapData, während das äußere data Data bleibt. Innerhalb eines Objekts kollidieren user_name und userName, das zweite Feld heißt dann userName2. Importiert wird com.fasterxml.jackson.annotation.JsonProperty, also das Jackson-2-Paket.

Objekte, Arrays und verschachtelte Modelle

Ein verschachteltes Objekt wird zu einer eigenen Klasse, benannt nach der Eigenschaft, die es hält; das Feld verweist auf diese Klasse. Arrays werden zu List<...>: Ein Array aus Zeichenketten ergibt List<String>, ein Array aus Objekten ergibt List<Users> plus die Klasse Users, und ein verschachteltes Array behält seine Tiefe, [[1,2]] wird zu List<List<Integer>>. Typargumente sind immer geboxt — List<Integer> und nie List<int> —, weil Java dort keine primitiven Typen erlaubt.

In einem Array aus Objekten wird jedes Element gelesen, nicht nur das erste: Ein Feld, das nur in manchen Elementen vorkommt, wird trotzdem ergänzt, Arrays in diesen Objekten werden zusammengeführt, und eine Eigenschaft mit unterschiedlichen Typen in verschiedenen Elementen wird Object. Ein leeres Array trägt gar keine Elementinformation, sein Element wird deshalb als Platzhalter String typisiert. Ein Array auf oberster Ebene wird genauso behandelt: Die Wurzelklasse entsteht aus den Eigenschaften aller Elemente.

Was die erzeugten Dateien sind — und was nicht

Jede Datei enthält eine Zeile package, die tatsächlich verwendeten Importe, einen kurzen Javadoc-Kopf mit Erzeugungszeitpunkt und der Adresse dieser Seite, eine öffentliche Klasse sowie private Felder mit je einem Getter und Setter. Lombok, Builder, equals und hashCode gibt es nicht: Die Ausgabe ist ein schlichter JavaBean, der das JDK und — bei umbenannten Feldern — die Jackson-Annotationen im Klassenpfad braucht.

Hier wird nichts kompiliert und nichts gegen Ihr Projekt geprüft, und die Typen stammen aus einem einzigen Beispiel. Optionale Felder, verschachtelte null-Werte oder ein Wert, der zwischen Aufrufen den Typ wechselt, können in diesem Beispiel nicht auftauchen; eine Zahl, die heute int ist, wird zu einem primitiven Feld, das Sie später vielleicht boxen müssen. Ein paar hundert Kilobyte wandeln sich im Browser in deutlich unter einer Sekunde um, ein großer Response ist also kein Problem — das Beispiel bleibt aber eine Momentaufnahme und kein Schema.

Zuletzt verwendet: