Les développeurs Java ont souvent envié JavaScript pour sa facilité d'analyse de JSON. Bien que Java offre plus de robustesse, il a tendance à impliquer plus de travail et de code passe-partout. Grâce au projet Manifold, Java a désormais le potentiel de surpasser JavaScript dans l'analyse et le traitement des fichiers JSON.
Manifold est un ensemble révolutionnaire d'extensions de langage pour Java qui change complètement la façon dont nous traitons JSON (et bien plus encore…).
Le code de ce tutoriel se trouve sur ma page GitHub . Manifold est relativement jeune mais déjà vaste dans ses capacités. Vous pouvez en savoir plus sur le projet sur leur site Web et sur la chaîne Slack.
Pour commencer, vous devrez installer le plug-in Manifold, qui n'est actuellement disponible que pour les IDE JetBrains. Le projet prend en charge les versions LTS de Java, y compris le dernier JDK 19.
Nous pouvons installer le plug-in à partir de l'interface utilisateur des paramètres IntelliJ/IDEAs en accédant au marché et en recherchant Manifold. Le plugin s'assure que l'IDE n'entre pas en collision avec le travail effectué par le plugin Maven/Gradle.
Manifold se compose de plusieurs projets plus petits, chacun offrant une extension de langue personnalisée. Aujourd'hui, nous allons discuter d'une telle extension, mais il y a beaucoup plus à explorer.
Pour démontrer Manifold, nous utiliserons un projet Maven simple (il fonctionne également avec Gradle). Nous devons d'abord coller la version actuelle de Manifold à partir de leur site Web et ajouter les dépendances nécessaires. La dépendance principale pour JSON est la dépendance manifold-json-rt
.
D'autres dépendances peuvent être ajoutées pour la prise en charge de YAML, XML et CSV. Nous devons l'ajouter au fichier pom.xml
du projet.
Je suis conscient de l'ironie où la réduction passe-partout pour JSON commence par une grande quantité de configuration dans le script de construction Maven. Mais il s'agit de configuration, pas de "code réel" ; c'est surtout du copier-coller.
Notez que si vous souhaitez réduire ce code, le code équivalent Gradle est laconique en comparaison.
Cette ligne doit aller dans la section des propriétés :
<manifold.version>2023.1.5</manifold.version>
Les dépendances que nous utilisons sont les suivantes :
<dependencies> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-json-rt</artifactId> <version>${manifold.version}</version> </dependency>
Le plugin de compilation est le passe-partout qui intègre Manifold dans le bytecode et le rend transparent pour nous. C'est la dernière partie de la configuration de pom :
<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>
Une fois la configuration terminée, plongeons dans le code.
Nous plaçons un exemple de fichier JSON dans le répertoire du projet sous la hiérarchie des ressources. J'ai placé ce fichier sous src/main/resources/com/debugagent/json/Test.json
:
{ "firstName": "Shai", "surname": "Almog", "website": "https://debugagent.com/", "active": true, "details":[ {"key": "value"} ] }
Dans la classe principale, nous actualisons le projet Maven et vous remarquerez qu'une nouvelle classe Test apparaît. Cette classe est créée dynamiquement par Manifold sur la base du fichier JSON. Si vous modifiez le JSON et actualisez Maven, tout se met à jour de manière transparente.
Il est important de comprendre que Manifold n'est pas un générateur de code. Il compile le JSON que nous venons d'écrire en bytecode.
La classe Test est fournie avec plusieurs fonctionnalités intégrées, telles qu'une API de générateur de type sécurisé qui vous permet de construire des objets JSON à l'aide de méthodes de générateur. Vous pouvez également générer des objets imbriqués et convertir le JSON en chaîne à l'aide des méthodes write()
et toJson()
.
Cela signifie que nous pouvons maintenant écrire :
Test test = Test.builder().withFirstName("Someone") .withSurname("Surname") .withActive(true) .withDetails(List.of( Test.details.detailsItem.builder(). withKey("Value 1").build() )) .build();
Qui imprimera le JSON suivant :
{ "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] }
Nous pouvons de la même manière lire un fichier JSON en utilisant un code tel que celui-ci :
Test readObject = Test.load().fromJson(""" { "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] } """);
Notez l'utilisation de la syntaxe Java 15 TextBlock
pour écrire une longue chaîne. La méthode load()
renvoie un objet qui inclut diverses API pour lire le JSON. Dans ce cas, il est lu à partir d'une String
mais il existe des API pour le lire à partir d'une URL, d'un fichier, etc.
Manifold prend en charge divers formats, notamment CSV, XML et YAML, vous permettant de générer et d'analyser n'importe lequel de ces formats sans écrire de code passe-partout ni sacrifier la sécurité des types. Afin d'ajouter cette prise en charge, nous devrons ajouter des dépendances supplémentaires au fichier pom.xml :
<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>
Avec ces dépendances supplémentaires, ce code imprimera les mêmes données que le fichier JSON... Avec test.write().toCsv()
la sortie serait :
"firstName","surname","active","details" "Someone","Surname","true","[manifold.json.rt.api.DataBindings@71070b9c]"
Notez que la sortie de valeurs séparées par des virgules (CSV) n'inclut pas les informations de hiérarchie. C'est une limitation du format CSV et non la faute de Manifold.
Avec test.write().toXml()
la sortie est familière et étonnamment concise :
<root_object firstName="Someone" surname="Surname" active="true"> <details key="Value 1"/> </root_object>
Avec test.write().toYaml()
nous obtenons à nouveau une impression familière :
firstName: Someone surname: Surname active: true details: - key: Value 1
Manifold fonctionne également de manière transparente avec le schéma JSON, vous permettant d'appliquer des règles et des contraintes strictes. Ceci est particulièrement utile lorsque vous travaillez avec des dates et des énumérations.
Manifold crée/met à jour de manière transparente le code octet qui adhère au schéma, ce qui facilite grandement le travail avec des données JSON complexes.
Ce schéma est copié et collé depuis le projet Manifold GitHub :
{ "$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"] }
C'est un schéma relativement simple, mais j'aimerais attirer votre attention sur plusieurs choses ici. Il définit le nom et l'e-mail selon les besoins. C'est pourquoi, lorsque nous essayons de créer un objet User
à l'aide d'un générateur dans Manifold, la méthode build()
nécessite les deux paramètres :
User.builder("Name", "[email protected]")
Ce n'est que le début... Le schéma inclut une date. Les dates sont une perspective douloureuse dans JSON, la normalisation est médiocre et pleine de problèmes. Le schéma comprend également un champ de genre qui est en fait une énumération.
Tout cela est converti en sémantique de type sécurisé à l'aide de classes Java courantes telles que LocalDate :
User u = User.builder("Name", "[email protected]") .withDate_of_birth(LocalDate.of(1999, 10, 11)) .withGender(User.Gender.male) .build();
Cela peut être encore plus court avec des importations statiques, mais l'essentiel de l'idée est clair. JSON est effectivement natif de Java dans Manifold.
Manifold est un projet puissant et passionnant. Il révolutionne l'analyse JSON en Java, mais ce n'est qu'une infime partie de ce qu'il peut faire !
Nous n'avons fait qu'effleurer la surface de ses capacités dans cet article. Dans le prochain article, nous approfondirons Manifold et explorerons quelques fonctionnalités supplémentaires inattendues.
Veuillez partager votre expérience et vos réflexions sur Manifold dans la section des commentaires. Si vous avez des questions, n'hésitez pas à demander.