JavaRush /Java Blog /Random-IT /Schema Json: perché e chi ne ha bisogno

Schema Json: perché e chi ne ha bisogno

Pubblicato nel gruppo Random-IT
Ciao, vagabondo. Oggi voglio raccontarvi una piccola magia. Probabilmente hai già sentito parlare di json. Questo è un linguaggio davvero universale: è compreso dalle macchine e facilmente letto dagli esseri umani. Ecco un tipico esempio di messaggio json:
{
   "помещение":{
      "название":"избушка",
      "разумна":true
   },
   "основание":{
      "тип":"курьи ноги",
      "количество":2
   },
   "проживающие":[
      {
         "Name":"Баба Яга",
         "профиль":"ведьма"
      }
   ],
   "местоположение":{
      "address":"граница леса"
   }
}
È conveniente comunicare così, non è vero? Se prima non sapevi cosa fosse JSON, ora lo sai. Come usarlo nel codice Java? Json è diventato un formato universale. Sta per JavaScript Object Notation, ma da tempo è andato oltre Javascript ed è utilizzato quasi ovunque. Java ha diverse librerie che semplificano il lavoro con json. Ecco i più famosi: Userò il secondo. Ne esistono 2 versioni : codehaus e fasterxml , non ho notato alcuna differenza, quindi puoi usarne qualsiasi qui. Ecco un pezzo di codice:
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue("сюда json", "сюда класс");
aiuterà a tradurre JSON in un oggetto. E ci stiamo avvicinando alla cosa più importante. Scrivere una classe per questo json. Puoi farlo manualmente, creare una struttura simile a questa:
-----------------------------------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;

}
Ho specificamente omesso getter, setter, costruttori e altri attributi pojo, altrimenti ti stancherai di sprecare =) Ora guarda qui:
{
  "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
}
Questo è il diagramma json della struttura sopra. Ora è il momento di spiegare perché ne hai bisogno. Eliminerà la necessità di scrivere classi e mantenerle. C'è un progetto così buono jsonschema2pojo . Offre plugin per costruttori di progetti (Maven, Gradle) che scriveranno queste classi per te in fase di creazione. Ecco un esempio dal mio progetto:
<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>
Questa è la sua impostazione. La cosa più interessante è qui:
<useCommonsLang3>true</useCommonsLang3>
<includeConstructors>true</includeConstructors>
<generateBuilders>true</generateBuilders>
<includeToString>true</includeToString>
<usePrimitives>true</usePrimitives>
Questa è un'istruzione su come scrivere una classe: useCommonsLang3 - usa la libreria CommonsLang3 includeConstructors - scriverà un costruttore generateBuilders - costruirà un generatore di modelli includeToString - aggiungi toString usePrimitives - un'istruzione per usare le primitive In che modo è migliore del codice scritto in casa ?
  1. Puoi personalizzare le classi con una riga. Ad esempio, devi aggiungere il suffisso Pojo a ciascuna classe. Basta aggiungere <classNameSuffix>Pojo</classNameSuffix> per assemblare il progetto e il gioco è fatto. Altrimenti, dovremmo cambiare manualmente i nomi di ciascuna classe.

    Ci sono molti di questi parametri, vale la pena leggerli tutti nella documentazione

  2. Se il tuo progetto ha un consumatore, sarà molto più semplice fornirgli schemi json anziché classi Java. Come ho già detto, gli schemi sono universali e il consumatore genererà semplicemente il pojo nella propria lingua.

  3. Sono molto più piccoli. L'esempio sopra contiene molte informazioni che non sono sempre necessarie, ad esempio modelli ed esempi. Ma se li restituisci al codice Java, crescerà anche molto. E non dimenticare il codice del modello, che nei diagrammi è indicato da un paio di impostazioni nel plugin, ma devi scriverlo tu stesso nel codice. E sì, conosco Lombok, c'è un'alternativa.

  4. Nessuna logica nel pojo. Quando le tue lezioni sono scritte da te, qualcuno potrebbe essere tentato di aggiungere un metodo conveniente per lui. Il metodo non può essere aggiunto allo schema json, così come alla classe generata.

Probabilmente è tutto.

Conclusione:

Ho cercato di trasmettere che gli schemi JSON sono un ottimo formato per l'interazione tra progetti. Un giorno l'ho incontrato durante un progetto ed è caduto nel mio cuore. Li uso quasi ovunque. Sì, questo non è sempre conveniente, perché per visualizzare i sorgenti è necessario assemblare il progetto. Ma questo è pojo, il che significa che non può esserci logica lì, e non ce ne sarà alcuna con i circuiti. PS... a volte mi spiego male, quindi ecco un video con un buon resoconto: Kirill Merkushev - La generazione di codice come modo per risolvere i problemi di automazione.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION