JavaRush /Java-Blog /Random-DE /Json-Schema: Warum und wer es braucht

Json-Schema: Warum und wer es braucht

Veröffentlicht in der Gruppe Random-DE
Hallo, Wanderer. Heute möchte ich Ihnen von etwas Magie erzählen. Sie haben wahrscheinlich schon von JSON gehört. Das ist so eine universelle Sprache: Sie wird von Maschinen verstanden und von Menschen leicht gelesen. Hier ist ein typisches Beispiel einer JSON-Nachricht:
{
   "помещение":{
      "название":"избушка",
      "разумна":true
   },
   "основание":{
      "тип":"курьи ноги",
      "количество":2
   },
   "проживающие":[
      {
         "Name":"Баба Яга",
         "профиль":"ведьма"
      }
   ],
   "местоположение":{
      "Adresse":"граница леса"
   }
}
Es ist praktisch, so zu kommunizieren, nicht wahr? Wenn Sie vorher nicht wussten, was JSON ist, wissen Sie es jetzt. Wie verwende ich dies im Java-Code? Json ist zu einem universellen Format geworden. Es steht für JavaScript Object Notation, geht aber längst über Javascript hinaus und wird fast überall verwendet. Java verfügt über mehrere Bibliotheken, die die Arbeit mit JSON erleichtern. Hier sind die bekanntesten: Ich werde das zweite verwenden. Es gibt zwei Versionen davon : Codehaus und Fasterxml . Mir sind keine Unterschiede aufgefallen, daher können Sie hier jede verwenden. Hier ist ein Codestück:
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue("сюда json", "сюда класс");
hilft dabei, JSON in ein Objekt zu übersetzen. Und wir nähern uns dem Wichtigsten. Schreiben einer Klasse für diesen JSON. Sie können dies manuell tun und eine Struktur wie diese erstellen:
-----------------------------------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;

}
Ich habe Getter, Setter, Konstruktoren und andere Pojo-Attribute ausdrücklich weggelassen, sonst würden Sie es satt haben, etwas zu verschwenden =) Schauen Sie jetzt hier:
{
  "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
}
Dies ist das JSON-Diagramm der obigen Struktur. Jetzt ist es an der Zeit zu erklären, warum Sie es brauchen. Dadurch entfällt die Notwendigkeit, Klassen zu schreiben und zu pflegen. Es gibt so ein gutes Projekt jsonschema2pojo . Es bietet Plugins für Projektentwickler (Maven, Gradle), die diese Klassen zur Erstellungszeit für Sie schreiben. Hier ist ein Beispiel aus meinem Projekt:
<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>
Das ist seine Einstellung. Das Interessanteste ist hier:
<useCommonsLang3>true</useCommonsLang3>
<includeConstructors>true</includeConstructors>
<generateBuilders>true</generateBuilders>
<includeToString>true</includeToString>
<usePrimitives>true</usePrimitives>
Dies ist eine Anleitung zum Schreiben einer Klasse: useCommonsLang3 – verwendet die CommonsLang3-Bibliothek includeConstructors – schreibt einen Konstruktor genericBuilders – erstellt einen Muster-Builder includeToString – fügt toString hinzu usePrimitives – eine Anweisung zur Verwendung von Grundelementen Wie ist das besser als selbst geschriebener Code? ?
  1. Sie können Klassen mit einer Zeile anpassen. Beispielsweise müssen Sie jeder Klasse das Suffix Pojo hinzufügen. Fügen Sie einfach <classNameSuffix>Pojo</classNameSuffix> hinzu, um das Projekt zusammenzustellen – und schon sind Sie fertig. Andernfalls müssten wir die Namen jeder Klasse manuell ändern.

    Es gibt viele dieser Parameter, es lohnt sich, sie alle in den Dokumenten zu lesen

  2. Wenn Ihr Projekt einen Verbraucher hat, ist es viel einfacher, ihm JSON-Schemas statt Java-Klassen zu geben. Wie ich bereits sagte, sind die Schemata universell und der Verbraucher generiert einfach Pojo in seiner eigenen Sprache.

  3. Sie sind viel kleiner. Das obige Beispiel enthält viele Informationen, die nicht immer notwendig sind, beispielsweise Muster und Beispiele. Wenn Sie sie jedoch auf Java-Code zurückführen, wird dieser ebenfalls stark wachsen. Und vergessen Sie nicht den Vorlagencode, der in den Diagrammen durch ein paar Einstellungen im Plugin angezeigt wird, Sie müssen ihn aber selbst in den Code schreiben. Und ja, ich weiß, was Lombok betrifft, es gibt eine Alternative.

  4. Keine Logik in Pojo. Wenn Sie Ihre Kurse selbst schreiben, könnte jemand versucht sein, eine für ihn geeignete Methode hinzuzufügen. Die Methode kann weder zum JSON-Schema noch zur generierten Klasse hinzugefügt werden.

Das ist wahrscheinlich alles.

Abschluss:

Ich habe versucht zu vermitteln, dass JSON-Schemata ein sehr gutes Format für die Interaktion zwischen Projekten sind. Eines Tages lernte ich ihn bei einem Projekt kennen und er fiel mir ins Herz. Ich benutze sie fast überall. Ja, das ist nicht immer praktisch, denn um die Quellen anzuzeigen, müssen Sie das Projekt zusammenstellen. Aber das ist Pojo, was bedeutet, dass es dort keine Logik geben kann und bei Schaltkreisen auch keine geben wird. PS.. manchmal erkläre ich schlecht, deshalb hier ein Video mit einem guten Bericht: Kirill Merkushev – Codegenerierung als Weg zur Lösung von Automatisierungsproblemen.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION