paint-brush
Como o Manifold revoluciona a análise JSON em Javapor@shai.almog
893 leituras
893 leituras

Como o Manifold revoluciona a análise JSON em Java

por Shai Almog8m2023/05/02
Read on Terminal Reader

Muito longo; Para ler

Analisar JSON em Java (e outros formatos) pode ser tão fácil quanto em JavaScript. Ele pode fazer muito mais, mantendo a segurança de tipo e a integração profunda do IDE.
featured image - Como o Manifold revoluciona a análise JSON em Java
Shai Almog HackerNoon profile picture

Os desenvolvedores de Java frequentemente invejam o JavaScript por sua facilidade de análise de JSON. Embora o Java ofereça mais robustez, ele tende a envolver mais trabalho e código clichê. Graças ao projeto Manifold, o Java agora tem o potencial de ofuscar o JavaScript na análise e processamento de arquivos JSON.


Manifold é um conjunto revolucionário de extensões de linguagem para Java que muda completamente a forma como lidamos com JSON (e muito mais…).

Introdução ao Manifold

O código deste tutorial pode ser encontrado na minha página do GitHub . O Manifold é relativamente jovem, mas já vasto em suas capacidades. Você pode saber mais sobre o projeto no site e no canal do Slack.


Para começar, você precisará instalar o plug-in Manifold, que atualmente está disponível apenas para IDEs JetBrains. O projeto suporta versões LTS de Java, incluindo o mais recente JDK 19.


Podemos instalar o plug-in a partir da IU de configurações do IntelliJ/IDEAs navegando até o marketplace e procurando por Manifold. O plug-in garante que o IDE não colida com o trabalho feito pelo plug-in Maven/Gradle.

Descrição da imagem

O Manifold consiste em vários projetos menores, cada um oferecendo uma extensão de idioma personalizada. Hoje, discutiremos uma dessas extensões, mas há muito mais a explorar.

Configurando um projeto Maven

Para demonstrar o Manifold, usaremos um projeto Maven simples (também funciona com Gradle). Primeiro precisamos colar a versão atual do Manifold de seu site e adicionar as dependências necessárias. A dependência principal para JSON é a dependência manifold-json-rt .


Outras dependências podem ser adicionadas para suporte a YAML, XML e CSV. Precisamos adicionar isso ao arquivo pom.xml no projeto.


Estou ciente da ironia de que a redução padronizada para JSON começa com uma grande quantidade de configuração no script de construção do Maven. Mas isso é configuração, não "código real"; é principalmente copiar e colar.


Observe que, se você deseja reduzir esse código, o código equivalente do Gradle é conciso em comparação.


Esta linha precisa ir para a seção de propriedades:

 <manifold.version>2023.1.5</manifold.version>


As dependências que usamos são essas:

 <dependencies>   <dependency>       <groupId>systems.manifold</groupId>       <artifactId>manifold-json-rt</artifactId>       <version>${manifold.version}</version>   </dependency>


O plug-in de compilação é o clichê que integra o Manifold no bytecode e o torna perfeito para nós. É a última parte da configuração do 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>

Com a configuração concluída, vamos mergulhar no código.

Analisando JSON com Manifold

Colocamos um arquivo JSON de amostra no diretório do projeto sob a hierarquia de recursos. Coloquei este arquivo em src/main/resources/com/debugagent/json/Test.json :

 { "firstName": "Shai", "surname": "Almog", "website": "https://debugagent.com/", "active": true, "details":[ {"key": "value"} ] }


Na classe principal, atualizamos o projeto Maven e você notará que uma nova classe Test aparece. Essa classe é criada dinamicamente pelo Manifold com base no arquivo JSON. Se você alterar o JSON e atualizar o Maven, tudo será atualizado perfeitamente.


É importante entender que o Manifold não é um gerador de código. Ele compila o JSON que acabamos de escrever em bytecode.


A classe Test vem com vários recursos integrados, como uma API de construtor de tipo seguro que permite construir objetos JSON usando métodos de construtor. Você também pode gerar objetos aninhados e converter o JSON em uma string usando os métodos write() e toJson() .


Isso significa que agora podemos escrever:

 Test test = Test.builder().withFirstName("Someone") .withSurname("Surname") .withActive(true) .withDetails(List.of( Test.details.detailsItem.builder(). withKey("Value 1").build() )) .build();


Que imprimirá o seguinte JSON:

 {  "firstName": "Someone",  "surname": "Surname",  "active": true,  "details": [    {      "key": "Value 1"    }  ] }


Da mesma forma, podemos ler um arquivo JSON usando um código como este:

 Test readObject = Test.load().fromJson(""" { "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] } """);


Observe o uso da sintaxe Java 15 TextBlock para escrever uma string longa. O método load() retorna um objeto que inclui várias APIs para leitura do JSON. Nesse caso, ele é lido de uma String , mas existem APIs para lê-lo de uma URL, arquivo etc.


O Manifold oferece suporte a vários formatos, incluindo CSV, XML e YAML, permitindo gerar e analisar qualquer um desses formatos sem escrever nenhum código clichê ou sacrificar a segurança do tipo. Para adicionar esse suporte, precisaremos adicionar dependências adicionais ao arquivo 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>


Com essas dependências adicionais, esse código imprimirá os mesmos dados do arquivo JSON... Com test.write().toCsv() a saída seria:

 "firstName","surname","active","details" "Someone","Surname","true","[manifold.json.rt.api.DataBindings@71070b9c]"


Observe que a saída de valores separados por vírgula (CSV) não inclui informações de hierarquia. Isso é uma limitação do formato CSV e não é culpa do Manifold.


Com test.write().toXml() a saída é familiar e surpreendentemente concisa:

 <root_object firstName="Someone" surname="Surname" active="true">  <details key="Value 1"/> </root_object>


Com test.write().toYaml() novamente obtemos uma impressão familiar:

 firstName: Someone surname: Surname active: true details: - key: Value 1

Trabalhando com esquema JSON

O Manifold também funciona perfeitamente com o esquema JSON, permitindo impor regras e restrições estritas. Isso é particularmente útil ao trabalhar com datas e enums.


O Manifold cria/atualiza perfeitamente o código de bytes que adere ao esquema, tornando muito mais fácil trabalhar com dados JSON complexos.


Este esquema é copiado e colado do projeto 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"] }


É um esquema relativamente simples, mas gostaria de chamar sua atenção para várias coisas aqui. Ele define nome e e-mail conforme necessário. É por isso que quando tentamos criar um objeto User usando um construtor no Manifold, o método build() requer ambos os parâmetros:

 User.builder("Name", "[email protected]")


Isso é apenas o começo... O esquema inclui uma data. As datas são uma perspectiva dolorosa em JSON, a padronização é ruim e repleta de problemas. O esquema também inclui um campo de gênero que é efetivamente uma enumeração.


Tudo isso é convertido em semântica de tipo seguro usando classes Java comuns, como LocalDate:

 User u = User.builder("Name", "[email protected]")       .withDate_of_birth(LocalDate.of(1999, 10, 11))       .withGender(User.Gender.male)       .build();


Isso pode ser ainda mais curto com importações estáticas, mas a essência da ideia é clara. JSON é efetivamente nativo para Java no Manifold.

A ponta do iceberg

Manifold é um projeto poderoso e empolgante. Ele revoluciona a análise JSON em Java, mas isso é apenas uma pequena parte do que ele pode fazer!


Nós apenas arranhamos a superfície de suas capacidades neste post. No próximo artigo, vamos nos aprofundar no Manifold e explorar alguns recursos adicionais inesperados.


Compartilhe sua experiência e pensamentos sobre o Manifold na seção de comentários. Se você tiver alguma dúvida, não hesite em perguntar.