JavaRush /Blog Java /Random-PL /Schemat Jsona: dlaczego i kto go potrzebuje

Schemat Jsona: dlaczego i kto go potrzebuje

Opublikowano w grupie Random-PL
Witaj wędrowcze. Dziś chcę Wam opowiedzieć o odrobinie magii. Prawdopodobnie słyszałeś już o jsonie. To taki uniwersalny język: jest rozumiany przez maszyny i łatwo czytany przez ludzi. Oto typowy przykład wiadomości json:
{
   "помещение":{
      "название":"избушка",
      "разумна":true
   },
   "основание":{
      "тип":"курьи ноги",
      "количество":2
   },
   "проживающие":[
      {
         "Nazwa":"Баба Яга",
         "профиль":"ведьма"
      }
   ],
   "местоположение":{
      "adres":"граница леса"
   }
}
Wygodna jest taka komunikacja, prawda? Jeśli wcześniej nie wiedziałeś, czym jest json, teraz już wiesz. Jak używać tego w kodzie Java? Json stał się formatem uniwersalnym. Skrót ten oznacza JavaScript Object Notation, ale już dawno wyszedł poza JavaScript i jest używany niemal wszędzie. Java ma kilka bibliotek, które ułatwiają pracę z jsonem. Oto najbardziej znane: Użyję tego drugiego. Są ich 2 wersje : codehaus i fastxml , nie zauważyłem między nimi żadnych różnic, więc możesz tutaj użyć dowolnej. Oto kawałek kodu:
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue("сюда json", "сюда класс");
pomoże przetłumaczyć json na obiekt. I dochodzimy do najważniejszego. Pisanie klasy dla tego jsona. Możesz to zrobić ręcznie, utwórz strukturę podobną do tej:
-----------------------------------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;

}
Specjalnie pominąłem moduły pobierające, ustawiające, konstruktory i inne atrybuty pojo, w przeciwnym razie znudziłoby ci się marnowanie =) Teraz spójrz tutaj:
{
  "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
}
To jest diagram JSON powyższej struktury. Teraz czas wyjaśnić, dlaczego tego potrzebujesz. Wyeliminuje to potrzebę pisania klas i ich utrzymywania. Jest taki dobry projekt jsonschema2pojo . Oferuje wtyczki dla twórców projektów (Maven, Gradle), które napiszą te klasy za Ciebie w czasie kompilacji. Oto przykład z mojego projektu:
<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>
To jest jego ustawienie. Najciekawsze jest tutaj:
<useCommonsLang3>true</useCommonsLang3>
<includeConstructors>true</includeConstructors>
<generateBuilders>true</generateBuilders>
<includeToString>true</includeToString>
<usePrimitives>true</usePrimitives>
Oto instrukcja jak napisać klasę: useCommonsLang3 - użyj biblioteki CommonsLang3 includeConstructors - napisze konstruktor generateBuilders - zbuduje konstruktor wzorców includeToString - dodaj toString usePrimitives - instrukcja użycia prymitywów W czym jest to lepsze niż kod napisany w domu ?
  1. Możesz dostosować zajęcia za pomocą jednej linii. Na przykład musisz dodać przyrostek Pojo do każdej klasy. Po prostu dodaj <classNameSuffix>Pojo</classNameSuffix>, aby złożyć projekt i gotowe. W przeciwnym razie musielibyśmy ręcznie zmieniać nazwy każdej klasy.

    Tych parametrów jest mnóstwo, warto o nich wszystkich przeczytać w dokumentacji

  2. Jeśli Twój projekt ma konsumenta, znacznie łatwiej będzie nadać mu schematy json niż klasy Java. Jak już mówiłem, schematy są uniwersalne i konsument po prostu wygeneruje pojo w swoim własnym języku.

  3. Są znacznie mniejsze. Powyższy przykład zawiera mnóstwo informacji, które nie zawsze są potrzebne, np. wzorce i przykłady. Ale jeśli zwrócisz je do kodu Java, również znacznie wzrośnie. I nie zapomnij o kodzie szablonu, który jest wskazany na diagramach przez kilka ustawień we wtyczce, ale musisz sam wpisać go w kodzie. I tak, wiem o Lomboku, istnieje alternatywa.

  4. Brak logiki w Pojo. Kiedy zajęcia są pisane samodzielnie, ktoś może ulec pokusie dodania metody, która będzie dla niego wygodna. Metody nie można dodać ani do schematu json, ani do wygenerowanej klasy.

To chyba wszystko.

Wniosek:

Próbowałem przekazać, że schematy json są bardzo dobrym formatem interakcji między projektami. Któregoś dnia spotkałam go przy projekcie i zapadł mi w serce. Używam ich niemal wszędzie. Tak, nie zawsze jest to wygodne, ponieważ aby przeglądać źródła, trzeba złożyć projekt. Ale to jest pojo, co oznacza, że ​​nie może być tam logiki i nie będzie jej w przypadku obwodów. PS.. czasami słabo tłumaczę, więc oto film z dobrym raportem: Kirill Merkushev - Generowanie kodu jako sposób na rozwiązanie problemów z automatyzacją.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION