JavaRush /Blogue Java /Random-PT /Esquema Json: por que e quem precisa dele

Esquema Json: por que e quem precisa dele

Publicado no grupo Random-PT
Olá, andarilho. Hoje quero falar sobre um pouco de magia. Você provavelmente já ouviu falar sobre json. Esta é uma linguagem universal: é compreendida pelas máquinas e facilmente lida pelos humanos. Aqui está um exemplo típico de mensagem json:
{
   "помещение":{
      "название":"избушка",
      "разумна":true
   },
   "основание":{
      "тип":"курьи ноги",
      "количество":2
   },
   "проживающие":[
      {
         "Name":"Баба Яга",
         "профиль":"ведьма"
      }
   ],
   "местоположение":{
      "address":"граница леса"
   }
}
É conveniente comunicar assim, não é? Se você não sabia o que era JSON antes, agora você sabe. Como usar isso em código Java? JSON se tornou um formato universal. Significa JavaScript Object Notation, mas há muito tempo foi além do javascript e é usado em quase todos os lugares. Java possui diversas bibliotecas que facilitam o trabalho com json. Aqui estão os mais famosos: Vou usar o segundo. Existem 2 versões deles : codehaus e fastxml , não notei nenhuma diferença entre eles, então você pode usar qualquer uma aqui. Aqui está um trecho de código:
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue("сюда json", "сюда класс");
ajudará a traduzir json em um objeto. E estamos nos aproximando do mais importante. Escrevendo uma aula para este json. Você pode fazer isso manualmente, criando uma estrutura mais ou menos assim:
-----------------------------------com.fairytale.Base.java-----------------------------------

package com.fairytale;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"type",
"quantity"
})
public class Base {

@JsonProperty("type")
public String type = "";
@JsonProperty("quantity")
public int quantity = 0;

}
-----------------------------------com.fairytale.Hut.java-----------------------------------

package com.fairytale;

import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"room",
"base",
"residents",
"location"
})
public class Hut {

@JsonProperty("room")
public Room room;
@JsonProperty("base")
public Base base;
@JsonProperty("residents")
public List<Resident> residents = new ArrayList<Resident>();
@JsonProperty("location")
public Location location;

}
-----------------------------------com.fairytale.Location.java-----------------------------------

package com.fairytale;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"address"
})
public class Location {

@JsonProperty("address")
public String address = "";

}
-----------------------------------com.fairytale.Resident.java-----------------------------------

package com.fairytale;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"name",
"profile"
})
public class Resident {

@JsonProperty("name")
public String name = "";
@JsonProperty("profile")
public String profile = "";

}
-----------------------------------com.fairytale.Room.java-----------------------------------

package com.fairytale;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"name",
"reasonable"
})
public class Room {

@JsonProperty("name")
public String name = "";
@JsonProperty("reasonable")
public boolean reasonable = false;

}
Omiti especificamente getters, setters, construtores e outros atributos do pojo, caso contrário você se cansaria de desperdiçar =) Agora veja aqui:
{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "room",
    "base",
    "residents",
    "location"
  ],
  "properties": {
    "room": {
      "$id": "#/properties/room",
      "type": "object",
      "title": "The Room Schema",
      "required": [
        "name",
        "reasonable"
      ],
      "properties": {
        "name": {
          "$id": "#/properties/room/properties/name",
          "type": "string",
          "title": "The Name Schema",
          "default": "",
          "examples": [
            "избушка"
          ],
          "pattern": "^(.*)$"
        },
        "reasonable": {
          "$id": "#/properties/room/properties/reasonable",
          "type": "boolean",
          "title": "The Reasonable Schema",
          "default": false,
          "examples": [
            true
          ]
        }
      },
	"additionalProperties": false
    },
    "base": {
      "$id": "#/properties/base",
      "type": "object",
      "title": "The Base Schema",
      "required": [
        "type",
        "quantity"
      ],
      "properties": {
        "type": {
          "$id": "#/properties/base/properties/type",
          "type": "string",
          "title": "The Type Schema",
          "default": "",
          "examples": [
            "курьи ноги"
          ],
          "pattern": "^(.*)$"
        },
        "quantity": {
          "$id": "#/properties/base/properties/quantity",
          "type": "integer",
          "title": "The Quantity Schema",
          "default": 0,
          "examples": [
            2
          ]
        }
      },
	"additionalProperties": false
    },
    "residents": {
      "$id": "#/properties/residents",
      "type": "array",
      "title": "The Residents Schema",
      "items": {
        "$id": "#/properties/residents/items",
        "type": "object",
        "title": "The Items Schema",
        "required": [
          "name",
          "profile"
        ],
        "properties": {
          "name": {
            "$id": "#/properties/residents/items/properties/name",
            "type": "string",
            "title": "The Name Schema",
            "default": "",
            "examples": [
              "Баба Яга"
            ],
            "pattern": "^(.*)$"
          },
          "profile": {
            "$id": "#/properties/residents/items/properties/profile",
            "type": "string",
            "title": "The Profile Schema",
            "default": "",
            "examples": [
              "ведьма"
            ],
            "pattern": "^(.*)$"
          }
        },
	    "additionalProperties": false
      }
    },
    "location": {
      "$id": "#/properties/location",
      "type": "object",
      "title": "The Location Schema",
      "required": [
        "address"
      ],
      "properties": {
        "address": {
          "$id": "#/properties/location/properties/address",
          "type": "string",
          "title": "The Address Schema",
          "default": "",
          "examples": [
            "граница леса"
          ],
          "pattern": "^(.*)$",
		  "additionalProperties": false
        }
      },
	"additionalProperties": false
    }
  },
	"additionalProperties": false
}
Este é o diagrama json da estrutura acima. Agora é hora de explicar por que você precisa disso. Isso eliminará a necessidade de escrever aulas e mantê-las. Existe um projeto tão bom jsonschema2pojo . Ele oferece plug-ins para construtores de projetos (Maven, Gradle) que escreverão essas classes para você no momento da construção. Aqui está um exemplo do meu projeto:
<plugin>
    <groupId>org.jsonschema2pojo</groupId>
    <artifactId>jsonschema2pojo-maven-plugin</artifactId>
    <version>0.4.37</version>

    <executions>
        <execution>
            <id>jsonschema2opjo</id>
            <configuration>
                <sourceDirectory>${project.basedir}/src/main/resources/json-schema/</sourceDirectory>
                <targetPackage>tester.model</targetPackage>
                <outputDirectory>${project.basedir}/target/generated-sources/jsonschema/</outputDirectory>
                <useCommonsLang3>true</useCommonsLang3>
                <includeConstructors>true</includeConstructors>
                <generateBuilders>true</generateBuilders>
                <includeToString>true</includeToString>
                <usePrimitives>true</usePrimitives>
            </configuration>
            <goals>
                <goal>generate</goal>
            </goals>
            <phase>generate-sources</phase>
        </execution>
    </executions>
</plugin>
Esta é a configuração dele. O mais interessante está aqui:
<useCommonsLang3>true</useCommonsLang3>
<includeConstructors>true</includeConstructors>
<generateBuilders>true</generateBuilders>
<includeToString>true</includeToString>
<usePrimitives>true</usePrimitives>
Esta é uma instrução sobre como escrever uma classe: useCommonsLang3 - use a biblioteca CommonsLang3 includeConstructors - escreverá um construtor generateBuilders - construirá um construtor de padrões includeToString - adicione toString usePrimitives - uma instrução para usar primitivas Como isso é melhor do que código escrito em casa ?
  1. Você pode personalizar classes com uma linha. Por exemplo, você precisa adicionar o sufixo Pojo a cada classe. Basta adicionar <classNameSuffix>Pojo</classNameSuffix> para montar o projeto - e pronto. Caso contrário, teríamos que alterar manualmente os nomes de cada classe.

    Existem muitos desses parâmetros, vale a pena ler sobre todos eles na documentação

  2. Se o seu projeto tiver um consumidor, será muito mais fácil fornecer esquemas JSON em vez de classes Java. Como já disse, os esquemas são universais e o consumidor simplesmente gerará o pojo na sua própria língua.

  3. Eles são muito menores. O exemplo acima contém muitas informações que nem sempre são necessárias, por exemplo, padrões e exemplos. Mas se você devolvê-los ao código java, ele também crescerá muito. E não se esqueça do código do modelo, que é indicado nos diagramas por algumas configurações do plugin, mas você mesmo deve escrevê-lo no código. E sim, eu sei sobre Lombok, existe uma alternativa.

  4. Nenhuma lógica no pojo. Quando suas aulas são escritas por você mesmo, alguém pode ficar tentado a adicionar um método que seja conveniente para ele. O método não pode ser adicionado ao esquema JSON, bem como à classe gerada.

Provavelmente é tudo.

Conclusão:

Tentei transmitir que os esquemas json são um formato muito bom para interação entre projetos. Um dia eu o conheci em um projeto e ele caiu no meu coração. Eu os uso em quase todos os lugares. Sim, isso nem sempre é conveniente, pois para visualizar as fontes é necessário montar o projeto. Mas isso é pojo, o que significa que não pode haver lógica ali, e não haverá lógica com circuitos. PS.. às vezes eu explico mal, então aqui está um vídeo com um bom relato: Kirill Merkushev - Geração de código como forma de resolver problemas de automação.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION