Java-Entwickler haben JavaScript oft wegen der einfachen JSON-Analyse beneidet. Obwohl Java robuster ist, erfordert es tendenziell mehr Arbeit und Boilerplate-Code. Dank des Manifold-Projekts hat Java nun das Potenzial, JavaScript beim Parsen und Verarbeiten von JSON-Dateien zu übertreffen.
Manifold ist ein revolutionärer Satz von Spracherweiterungen für Java, der die Art und Weise, wie wir mit JSON umgehen, völlig verändert (und noch viel mehr …).
Den Code für dieses Tutorial finden Sie auf meiner GitHub-Seite . Manifold ist relativ jung, verfügt aber bereits über umfangreiche Möglichkeiten. Mehr über das Projekt erfahren Sie auf ihrer Website und im Slack-Kanal.
Zunächst müssen Sie das Manifold-Plugin installieren, das derzeit nur für JetBrains-IDEs verfügbar ist. Das Projekt unterstützt LTS-Versionen von Java, einschließlich des neuesten JDK 19.
Wir können das Plugin über die Benutzeroberfläche der IntelliJ/IDEA-Einstellungen installieren, indem wir zum Marktplatz navigieren und nach Manifold suchen. Das Plugin stellt sicher, dass die IDE nicht mit der Arbeit des Maven/Gradle-Plugins kollidiert.
Manifold besteht aus mehreren kleineren Projekten, die jeweils eine benutzerdefinierte Spracherweiterung bieten. Heute werden wir eine solche Erweiterung besprechen, aber es gibt noch viel mehr zu erkunden.
Um Manifold zu demonstrieren, verwenden wir ein einfaches Maven-Projekt (es funktioniert auch mit Gradle). Wir müssen zunächst die aktuelle Manifold-Version von ihrer Website einfügen und die erforderlichen Abhängigkeiten hinzufügen. Die Hauptabhängigkeit für JSON ist die manifold-json-rt
Abhängigkeit.
Für die YAML-, XML- und CSV-Unterstützung können weitere Abhängigkeiten hinzugefügt werden. Wir müssen dies zur Datei pom.xml
im Projekt hinzufügen.
Ich bin mir der Ironie bewusst, dass die Standardreduzierung für JSON mit einem großen Konfigurationsaufwand im Maven-Build-Skript beginnt. Dies ist jedoch eine Konfiguration, kein „eigentlicher Code“; Es ist meistens Kopieren und Einfügen.
Beachten Sie, dass der Gradle-Äquivalentcode vergleichsweise knapp ist, wenn Sie diesen Code reduzieren möchten.
Diese Zeile muss in den Eigenschaftenbereich eingefügt werden:
<manifold.version>2023.1.5</manifold.version>
Die von uns verwendeten Abhängigkeiten sind folgende:
<dependencies> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-json-rt</artifactId> <version>${manifold.version}</version> </dependency>
Das Kompilierungs-Plugin ist das Boilerplate, das Manifold in den Bytecode einbindet und es für uns nahtlos macht. Dies ist der letzte Teil des Pom-Setups:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>19</source> <target>19</target> <encoding>UTF-8</encoding> <compilerArgs> <!-- Configure manifold plugin--> <arg>-Xplugin:Manifold</arg> </compilerArgs> <!-- Add the processor path for the plugin --> <annotationProcessorPaths> <path> <groupId>systems.manifold</groupId> <artifactId>manifold-json</artifactId> <version>${manifold.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
Nachdem die Einrichtung abgeschlossen ist, tauchen wir in den Code ein.
Wir platzieren eine Beispiel-JSON-Datei im Projektverzeichnis unter der Ressourcenhierarchie. Ich habe diese Datei unter src/main/resources/com/debugagent/json/Test.json
abgelegt:
{ "firstName": "Shai", "surname": "Almog", "website": "https://debugagent.com/", "active": true, "details":[ {"key": "value"} ] }
In der Hauptklasse aktualisieren wir das Maven-Projekt und Sie werden feststellen, dass eine neue Testklasse angezeigt wird. Diese Klasse wird von Manifold dynamisch basierend auf der JSON-Datei erstellt. Wenn Sie JSON ändern und Maven aktualisieren, wird alles nahtlos aktualisiert.
Es ist wichtig zu verstehen, dass Manifold kein Codegenerator ist. Es kompiliert den JSON, den wir gerade geschrieben haben, in Bytecode.
Die Testklasse verfügt über mehrere integrierte Funktionen, beispielsweise eine typsichere Builder-API, mit der Sie JSON-Objekte mithilfe von Builder-Methoden erstellen können. Sie können auch verschachtelte Objekte generieren und den JSON-Code mit den Methoden write()
und toJson()
in einen String konvertieren.
Das heißt, wir können jetzt schreiben:
Test test = Test.builder().withFirstName("Someone") .withSurname("Surname") .withActive(true) .withDetails(List.of( Test.details.detailsItem.builder(). withKey("Value 1").build() )) .build();
Dadurch wird der folgende JSON-Code ausgedruckt:
{ "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] }
Auf ähnliche Weise können wir eine JSON-Datei mit Code wie diesem lesen:
Test readObject = Test.load().fromJson(""" { "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] } """);
Beachten Sie die Verwendung der Java 15 TextBlock
Syntax zum Schreiben einer langen Zeichenfolge. Die Methode load()
gibt ein Objekt zurück, das verschiedene APIs zum Lesen des JSON enthält. In diesem Fall wird es aus einem String
gelesen, es gibt jedoch APIs zum Lesen aus einer URL, Datei usw.
Manifold unterstützt verschiedene Formate, darunter CSV, XML und YAML, sodass Sie jedes dieser Formate generieren und analysieren können, ohne Boilerplate-Code schreiben oder die Typsicherheit opfern zu müssen. Um diese Unterstützung hinzuzufügen, müssen wir der Datei pom.xml zusätzliche Abhängigkeiten hinzufügen:
<dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-csv-rt</artifactId> <version>${manifold.version}</version> </dependency> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-xml-rt</artifactId> <version>${manifold.version}</version> </dependency> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-yaml-rt</artifactId> <version>${manifold.version}</version> </dependency> </dependencies>
Mit diesen zusätzlichen Abhängigkeiten gibt dieser Code dieselben Daten aus wie die JSON-Datei ... Mit test.write().toCsv()
wäre die Ausgabe:
"firstName","surname","active","details" "Someone","Surname","true","[manifold.json.rt.api.DataBindings@71070b9c]"
Beachten Sie, dass die CSV-Ausgabe (Comma Separated Values) keine Hierarchieinformationen enthält. Das ist eine Einschränkung des CSV-Formats und nicht die Schuld von Manifold.
Bei test.write().toXml()
ist die Ausgabe bekannt und überraschend prägnant:
<root_object firstName="Someone" surname="Surname" active="true"> <details key="Value 1"/> </root_object>
Mit test.write().toYaml()
erhalten wir wieder einen bekannten Ausdruck:
firstName: Someone surname: Surname active: true details: - key: Value 1
Manifold funktioniert auch nahtlos mit dem JSON-Schema, sodass Sie strenge Regeln und Einschränkungen durchsetzen können. Dies ist besonders nützlich, wenn Sie mit Datumsangaben und Aufzählungen arbeiten.
Manifold erstellt/aktualisiert nahtlos Bytecode, der dem Schema entspricht, was die Arbeit mit komplexen JSON-Daten erheblich erleichtert.
Dieses Schema wurde aus dem GitHub-Projekt Manifold kopiert und eingefügt:
{ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://example.com/schemas/User.json", "type": "object", "definitions": { "Gender": { "type": "string", "enum": ["male", "female"] } }, "properties": { "name": { "type": "string", "description": "User's full name.", "maxLength": 80 }, "email": { "description": "User's email.", "type": "string", "format": "email" }, "date_of_birth": { "type": "string", "description": "Date of uses birth in the one and only date standard: ISO 8601.", "format": "date" }, "gender": { "$ref" : "#/definitions/Gender" } }, "required": ["name", "email"] }
Es ist ein relativ einfaches Schema, aber ich möchte Ihre Aufmerksamkeit hier auf einige Dinge lenken. Es definiert Name und E-Mail nach Bedarf. Aus diesem Grund benötigt die build()
-Methode beide Parameter, wenn wir versuchen, ein User
mit einem Builder in Manifold zu erstellen:
User.builder("Name", "[email protected]")
Das ist erst der Anfang ... Das Schema enthält ein Datum. Datumsangaben sind in JSON eine problematische Angelegenheit, die Standardisierung ist schlecht und voller Probleme. Das Schema enthält auch ein Geschlechtsfeld, bei dem es sich praktisch um eine Aufzählung handelt.
Dies alles wird mithilfe gängiger Java-Klassen wie LocalDate in typsichere Semantik umgewandelt:
User u = User.builder("Name", "[email protected]") .withDate_of_birth(LocalDate.of(1999, 10, 11)) .withGender(User.Gender.male) .build();
Mit statischen Importen lässt sich das noch verkürzen, aber der Kern der Idee ist klar. JSON ist in Manifold praktisch nativ für Java.
Manifold ist ein kraftvolles und aufregendes Projekt. Es revolutioniert das JSON-Parsing in Java, aber das ist nur ein kleiner Teil dessen, was es kann!
Wir haben in diesem Beitrag nur an der Oberfläche seiner Fähigkeiten gekratzt. Im nächsten Artikel werden wir tiefer in Manifold eintauchen und einige zusätzliche unerwartete Funktionen erkunden.
Bitte teilen Sie Ihre Erfahrungen und Gedanken zu Manifold im Kommentarbereich mit. Wenn Sie Fragen haben, zögern Sie nicht, diese zu stellen.