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…).
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.
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.
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.
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
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.
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.