JavaRush /Blog Java /Random-ES /Esquema Json: por qué y quién lo necesita

Esquema Json: por qué y quién lo necesita

Publicado en el grupo Random-ES
Hola vagabundo. Hoy quiero hablaros de un poco de magia. Probablemente ya hayas oído hablar de json. Este es un lenguaje universal: las máquinas lo entienden y los humanos lo leen fácilmente. A continuación se muestra un ejemplo típico de un mensaje json:
{
   "помещение":{
      "название":"избушка",
      "разумна":true
   },
   "основание":{
      "тип":"курьи ноги",
      "количество":2
   },
   "проживающие":[
      {
         "Nombre":"Баба Яга",
         "профиль":"ведьма"
      }
   ],
   "местоположение":{
      "DIRECCIÓN":"граница леса"
   }
}
Es conveniente comunicarse así, ¿no? Si antes no sabías qué era json, ahora lo sabes. ¿Cómo usar esto en código java? Json se ha convertido en un formato universal. Significa notación de objetos JavaScript, pero hace mucho que va más allá de JavaScript y se usa en casi todas partes. Java tiene varias bibliotecas que facilitan el trabajo con json. Aquí están los más famosos: Usaré el segundo. Hay 2 versiones de ellos : codehaus y fastxml , no noté ninguna diferencia en ellos, así que puedes usar cualquiera aquí. Aquí hay un fragmento de código:
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue("сюда json", "сюда класс");
ayudará a traducir json en un objeto. Y nos acercamos a lo más importante. Escribiendo una clase para este json. Puedes hacer esto manualmente, crear una estructura similar a esta:
-----------------------------------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;

}
Omití específicamente captadores, definidores, constructores y otros atributos de pojo, de lo contrario te cansarías de desperdiciar =) Ahora mira aquí:
{
  "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 es el diagrama json de la estructura anterior. Ahora es el momento de explicar por qué lo necesitas. Eliminará la necesidad de escribir clases y mantenerlas. Existe un proyecto tan bueno jsonschema2pojo . Ofrece complementos para creadores de proyectos (Maven, Gradle) que escribirán estas clases por usted en el momento de la compilación. Aquí hay un ejemplo de mi proyecto:
<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>
Este es su escenario. Lo más interesante está aquí:
<useCommonsLang3>true</useCommonsLang3>
<includeConstructors>true</includeConstructors>
<generateBuilders>true</generateBuilders>
<includeToString>true</includeToString>
<usePrimitives>true</usePrimitives>
Esta es una instrucción sobre cómo escribir una clase: useCommonsLang3 - use la biblioteca CommonsLang3 includeConstructors - escribirá un constructor generateBuilders - construirá un generador de patrones includeToString - agregará toString usePrimitives - una instrucción para usar primitivas ¿Cómo es esto mejor que el código escrito en casa? ?
  1. Puedes personalizar las clases con una línea. Por ejemplo, debes agregar el sufijo Pojo a cada clase. Simplemente agregue <classNameSuffix>Pojo</classNameSuffix> para ensamblar el proyecto y listo. De lo contrario, tendríamos que cambiar los nombres de cada clase manualmente.

    Hay muchos de estos parámetros, vale la pena leerlos todos en los documentos.

  2. Si su proyecto tiene un consumidor, será mucho más fácil darle esquemas json en lugar de clases java. Como ya dije, los esquemas son universales y el consumidor simplemente generará pojo en su propio idioma.

  3. Son mucho más pequeños. El ejemplo anterior contiene mucha información que no siempre es necesaria, por ejemplo, patrones y ejemplos. Pero si los devuelve al código Java, también crecerá mucho. Y no te olvides del código de la plantilla, que se indica en los diagramas mediante un par de configuraciones en el complemento, pero debes escribirlo tú mismo en el código. Y sí, conozco Lombok, hay una alternativa.

  4. No hay lógica en pojo. Cuando sus clases las escribe usted mismo, alguien puede verse tentado a agregar un método que le resulte conveniente. El método no se puede agregar al esquema json ni a la clase generada.

Probablemente eso sea todo.

Conclusión:

Intenté transmitir que los esquemas json son un muy buen formato para la interacción entre proyectos. Un día lo conocí en un proyecto y cayó en mi corazón. Los uso en casi todas partes. Sí, esto no siempre es conveniente, porque para ver las fuentes es necesario ensamblar el proyecto. Pero esto es pojo, lo que significa que no puede haber lógica allí, y no la habrá con los circuitos. PD... a veces me explico mal, así que aquí tenéis un vídeo con un buen informe: Kirill Merkushev - La generación de código como forma de resolver problemas de automatización.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION