Do czego służy YAML?

Innym formatem danych tekstowych jest YAML ( Jeszcze inny język znaczników , później - YAML Ain't Markup Language ). Służy do serializacji obiektów do transmisji przez sieć (tak samo jak używane są xml i json). Ze względu na swoją czytelność służy również do pisania plików konfiguracyjnych np. dla Docker, Kubernetes, Ansible itp. Jeśli YAML musi zostać zapisany do pliku (na przykład pliku konfiguracyjnego), używane są dwa rozszerzenia: .yaml i .yml.

Składnia języka

Do oznaczenia znaczników w xml stosuje się nawiasy kątowe ( <> ), dla JSON - nawiasy klamrowe ( {} ). W przypadku YAML używane są separatory wierszy (Enter) i wcięcia (spacje lub tabulatory).

Dane są przechowywane jako pary klucz-wartość, gdzie kluczem jest łańcuch, a wartością mogą być różne typy danych: łańcuch, liczba, prawda/fałsz, tablica... Klucze są zapisywane bez cudzysłowów.

Przyjrzyjmy się, jak informacje są przechowywane w YAML:

Typ Jawa YAML
Liczba całkowita
int number = 5
numer 5
Liczba ułamkowa
double number = 4.3
liczba: 4.3
zmienna logiczna
boolean valid = false
ważny: fałszywy
ważny: nie
ważny: wyłączony

* Prawidłowe wartości logiczne: prawda/fałsz, tak/nie, wł./wył.

Linia
String city = "New York"
miasto: Kijów
miasto: „Kijów”
miasto: „Kijów”

* Wszystkie trzy opcje są równoważne.

Ciąg ze znakami specjalnymi
String line = "aaa\nbbb"
wiersz: „aaa\nbbb”
Komentarz w kodzie
// comment
# komentarz
Obiekt
public class Person {
  String name = "Dennis";
  int age = 32;
}

* Klasa obiektu jest podawana tak, aby widoczna była struktura obiektu.

osoba:
  imię: "Wasyl"
  wiek: 32 lata

* Zwróć uwagę na wcięcie przed atrybutami. Musi być taki sam dla wszystkich atrybutów.

Lista liczb pierwszych
var ages =
    List.of(1, 3, 5, 9, 78, -5);
wiek: [1, 3,5,9,78, -5]
wiek:
  - 1
  - 3
  - 5
  - 9
  - 78
  - -5

* Obie opcje są równoważne.
** Każdy kolejny element listy jest oznaczony łącznikiem.

Lista obiektów
class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}List<Person> people = List.of(
        new Person("Ian", 21),
        new Person("Marina", 25),
        new Person("Owen", 73)      );
osoby:
  - ​​imię: "Ivan"
    wiek: 21
  - imię i nazwisko: "Marina"
    wiek: 25 lat
  - imię i nazwisko: "Oleh"
    wiek: 73

Podobnie jak w Javie, elementem listy może być lista, to znaczy obiekty mogą być zagnieżdżane jeden w drugim. Łącznik, który definiuje następny element listy, może być przesunięty poziomo w stosunku do klucza nadrzędnego lub umieszczony bezpośrednio pod nim. Najważniejsze jest to, że wszystkie elementy mają ten sam format. Pomoże to uniknąć nieporozumień i niejasności związanych z hierarchią zagnieżdżania.

wiek:
  - 1
  - 3
  - 5
  - 9
  - 78
  - -5
wiek:
- 1
- 3
- 5
- 9
- 78
- -5

Istnieją jeszcze dwa niuanse podczas pracy z wartościami tekstowymi:

  1. Tekst wielowierszowy. Możemy zapisać tekst w następujący sposób:

    multilineText: "linia 1\nlinia 2\n...linia n"

    Ale czytanie go będzie bardzo niewygodne. Dlatego istnieje symbol | (pipe), za pomocą którego możesz napisać tekst inaczej:

    tekst wielowierszowy: |
     linia 1
     linia 2
     ....
     linia n

    Zgadzam się, druga opcja jest wygodniejsza, prawda?

  2. Długie linie. Jeśli chcesz zachować tekst w jednym wierszu, ale nadal chcesz, aby mieścił się w widocznym obszarze roboczym IDE, możesz użyć symbolu > (większy).

    singlelineText: >
     zacznij
     ...
     kontynuuj tę samą linię
     ...
     koniec

    Cały tekst będzie traktowany jako jedna linia.

Jeśli istnieje potrzeba zapisania kilku struktur danych YAML w jednym pliku, to pomiędzy nimi należy zastosować separator - (trzy łączniki). W praktyce potrzeba jest rzadka, ale lepiej mieć świadomość tej opcji.

Przykładowy dokument YAML

Stwórzmy w Javie jakąś strukturę danych (klasę) i obiekt tego typu - i spróbujmy przedstawić dane tego obiektu w postaci serializowanej w formacie YAML.

class Family {
   private Date weddingDate;
   private Person wife;
   private Person husband;
   private List<Person> children;

   // Getters and setters are omitted
}

class Person {
   private final String name;
   private final boolean isWoman;
   private int age;

   public Person(String name, int age, boolean isWoman) {
       this.name = name;
       this.age = age;
       this.isWoman = isWoman;
   }

// Getters and setters are omitted

}

public static void main(String[] args) {
   Person wife = new Person("Ann", 37, true);
   Person husband = new Person("Alex", 40, false);
   var children = List.of(
           new Person("Iris", 12, true),
           new Person("Olivia", 5, true)
   );
   Date weddingDate = new Date(/* some long */);

   Family family = new Family();
   family.setWeddingDate(weddingDate);
   family.setWife(wife);
   family.setHusband(husband);
   family.setChildren(children);
}

Prawidłowa reprezentacja w YAML:

---
ślubData: 2000-12-03
żona:
 imię: Anya
 wiek: 37 lat
 Kobieta: tak
mąż:
 imię: Alex
 wiek: 40 lat
 Kobieta: bez
dzieci:
 - imię: Inna
   wiek: 12 lat
   Kobieta: prawda
 - imię: Olya
   wiek: 5
   isKobieta: prawda
---