Перетворіть масив YAML на список Java за допомогою SnakeYAML

Вступ

ЯМЛ є однією з найпопулярніших мов серіалізації даних після JSON. Тому його іноді називають a строгий суперсет JSON. Він був розроблений для взаємодії з людьми та читабельності з самого початку, тому він відомий своєю простотою. Його розроблено з урахуванням гнучкості та доступності, тому він працює з усіма сучасними мовами програмування та потужним форматом для запису конфігураційних файлів. Він також використовується для збереження даних, обміну повідомленнями в Інтернеті, міжмовного обміну даними та багатьох інших параметрів.

YAML було запущено в 2001 році і називалося «Ще одна мова розмітки" в той час. Але пізніше він був позначений як «YAML не є мовою розмітки“. Основною структурою файлу YAML є a карта. Він також відомий як словник, хеш (карта) або просто об’єктний, залежно від мови програмування, яку ми вибрали.

Пробіли та відступи використовуються у файлах YAML для позначення вкладеності.

примітки: для відступів у файлах YAML можна використовувати лише пробіли; символи табуляції заборонені. Поки відступи виконуються послідовно, не має значення, скільки пробілів використовується.

Синтаксис YAML

Формат YAML переважно використовує 3 типи вузлів:

  • Карти/Словники: карта Вміст вузла є невпорядкованою колекцією ключ/значення вузол пар, з вимогою, щоб кожен ключ був окремим. Жодних додаткових обмежень YAML не накладає на вузли.
  • Масиви/Списки: An масив Вміст вузла - це впорядкована колекція нуля або більше вузлів. Зокрема, послідовність може включати один і той же вузол більше одного разу. Він може містити навіть сам себе.
  • Літерали (Рядки, числа, логічні значення тощо): послідовність нуля або більше Символи Unicode можна використовувати для представлення непрозорих даних, які складають a скалярний вміст вузла.

У цій статті ми конкретно розглянемо перетворення вмісту масиву YAML у список у Java. Існує багато відкритих бібліотек, але найпопулярніші з них Джексон та ЗміяYAML. У цьому посібнику ми будемо використовувати SnakeYaml як нашу бібліотеку для аналізу вмісту YAML.

SnakeYaml

ЗміяYAML — це пакет аналізу YAML, який пропонує API високого рівня для серіалізації та десеріалізації документів YAML. Точкою входу для SnakeYAML є Yaml клас. Документи або файли YAML можна завантажити за допомогою load() методом або пакетно через loadAll() метод. Методи також беруть справжні дані YAML у формі об’єктів String InputStreams, що є типовим типом файлу.

З огляду на : структуру, вроджену для файлів YAML, з якою SnakeYAML природно працює Карти Java, але ми також можемо використовувати унікальний Об'єкти Java.

Щоб включити бібліотеку в наш проект, додайте таку залежність до свого pom.xml Файл:

<dependencies>
    <dependency>
        <groupId>org.yaml</groupId>
        <artifactId>snakeyaml</artifactId>
        <version>1.33</version>
    </dependency>
</dependencies>

Або, якщо ви використовуєте Gradle:

compile group: 'org.yaml', name: 'snakeyaml', version: '1.33'

Читання простого масиву YAML

Давайте швидко почнемо з читання простого масиву з файлу YAML. Припустімо, що у папці ресурсів нашого проекту Java є файл yaml із такими даними:

- One
- Two
- Three
- Four

Тоді ми можемо завантажити вміст файлу як InputStream. Далі ми побудуємо Yaml екземпляр, який потім діятиме як точка входу для доступу до бібліотеки та об’єкта для програмного представлення вмісту файлу YAML. The load() метод дозволяє читати та аналізувати будь-який InputStream з дійсними даними YAML:

public void readYamlWithArray() {
    InputStream inputStream = this.getClass()
            .getClassLoader()
            .getResourceAsStream("number.yml");
    Yaml yaml = new Yaml();
    List data = yaml.load(inputStream);
    System.out.println(data);
 }

Метод поверне Java List рядкових даних. Якщо ми надрукуємо data то це дасть такий результат:

[One, Two, Three, Four]

Читання згрупованого масиву YAML

Іноді нам хочеться визначити масив вмісту за заданим ключем. Це називається групуванням масивів у вузол карти YAML. Зразок YAML такого типу виглядає так:

languages:
  - Java
  - JavaScript
  - Python
  - Golang
  - Perl
  - Shell
  - Scala

Це можна вважати Java Map що містять a : де значення an масив. Отже, дані все ще завантажуватимуться як InputStream як ми визначили вище. Але data необхідно визначити як Map of List of Strings:

public void readYamlWithArrayGroup() {
    InputStream inputStream = this.getClass()
            .getClassLoader()
            .getResourceAsStream("language.yml");
    Yaml yaml = new Yaml();
    Map<String, List> data = yaml.load(inputStream);
    System.out.println(data);
    
    data.values()
            .stream()
            .collect(Collectors.toList())
            .get(0)
            .forEach(System.out::println);
}

Тепер, якщо ми прочитаємо наш data, це виглядатиме приблизно так:

{languages=[Java, JavaScript, Python, Golang, Perl, Shell, Scala]}
Java
JavaScript
Python
Golang
Perl
Shell
Scala

Читання багаторядкового масиву масивів YAML

Іноді ми зустрічаємо файл YAML з даними, що містять масив масивів. Наприклад, ми групуємо курси та представляємо їх у вигляді масиву масивів, як показано нижче:

courses:
  - - C
    - Java
    - Data Structures
    - Algorithms
  - - Big Data
    - Spark
    - Kafka
    - Machine Learning

Це можна розібрати як Java Map of List of List of String. Ми можемо знову завантажити InputStream як ми робили раніше. Але дані будуть завантажені так:

Ознайомтеся з нашим практичним практичним посібником із вивчення Git з передовими методами, прийнятими в галузі стандартами та включеною шпаргалкою. Припиніть гуглити команди Git і фактично вчитися це!

public void readYamlWithMultiLineArrayGroup() {
    InputStream inputStream = this.getClass()
            .getClassLoader()
            .getResourceAsStream("courses.yml");
    Yaml yaml = new Yaml();
    
    Map<String, List<List>> data = yaml.load(inputStream);
    System.out.println(data);
    
    System.out.println("First Array Group:");
    data.values()
            .stream()
            .collect(Collectors.toList())
            .get(0)
            .get(0)
            .forEach(System.out::println);
    
    System.out.println("nSecond Array Group:");
    data.values()
            .stream()
            .collect(Collectors.toList())
            .get(0)
            .get(1)
            .forEach(System.out::println);
}

Отже, якщо ми надрукуємо data, це виглядатиме приблизно так:

{courses=[[C, Java, Data Structures, Algorithms], [Big Data, Spark, Kafka, Machine Learning]]}

First Array Group:
C
Java
Data Structures
Algorithms

Second Array Group:
Big Data
Spark
Kafka
Machine Learning

Читання складного вкладеного вмісту YAML як Java Bean

Ми побачили, як ми можемо обробляти вміст типу масиву окремо, але зі складними вкладеними файлами YAML – мати карту карт зі списками списків важко інтуїтивно проаналізувати та важко мати справу. Навіть в останньому прикладі, де ми мали лише два вкладені списки, обробка їх як списків стає досить багатослівною.

У цих випадках найкраще створити POJO, який можна зіставити з вкладеними даними YAML. Давайте спочатку створимо зразок YAML, що містить вкладений вміст веб-сайту:

website: stackabuse
skills:
  - python
  - javascript
  - java
  - unix
  - machine learning
  - web development
tutorials:
  - graphs:
      name: Graphs in Python - Theory and Implementation
      tags:
        - python
        - data structures
        - algorithm
      contributors:
        - David Landup
        - Dimitrije Stamenic
        - Jovana Ninkovic
      last_updated: June 2022
  - git:
      name: Git Essentials - Developer's Guide to Git
      tags:
        - git
      contributors:
        - David Landup
        - François Dupire
        - Jovana Ninkovic
      last_updated: April 2022
  - deep learning:
      name: Practical Deep Learning for Computer Vision with Python
      tags:
        - python
        - machine learning
        - tensorflow
        - computer vision
      contributors:
        - David Landup
        - Jovana Ninkovic
      last_updated: October 2022
published: true

Нам потрібно визначити батьківський клас Java WebsiteContent що складатиметься з List навичок і a List of Map посібників, які знову міститимуть списки тегів і учасників:

public class WebsiteContent {
    private String website;
    private List skills;
    private List<Map> tutorials;
    private Boolean published;

    

    @Override
    public String toString() {
        return "WebsiteContent{" +
                "website='" + website + ''' +
                ", skills=" + skills +
                ", tutorials=" + tutorials +
                ", published=" + published +
                '}';
    }
}
public class Tutorial {

    private String name;
    private List tags;
    private List contributors;
    private String lastUpdated;

    

    @Override
    public String toString() {
        return "Tutorial{" +
                "name='" + name + ''' +
                ", tags=" + tags +
                ", contributors=" + contributors +
                ", lastUpdated='" + lastUpdated + ''' +
                '}';
    }
}

Тепер ми можемо знову завантажити дані з файлу as InputStream як ми робили раніше. Далі, коли ми створимо свій Yaml об’єкт класу, нам потрібно вказати тип даних, до якого ми хочемо привести дані. The new Constructor(WebsiteContent.class) повідомляє SnakeYAML прочитати дані з файлу YAML, зіставити його з нашим WebsiteContent об'єкт

Відображення є простим, і імена атрибутів наших об’єктів мають збігатися з іменами атрибутів YAML.

public void readYamlAsBeanWithNestedArrays(){
    
    InputStream inputStream = this.getClass()
            .getClassLoader()
            .getResourceAsStream("website_content.yml");
            
    
    Yaml yaml = new Yaml(new Constructor(WebsiteContent.class));
    WebsiteContent data = yaml.load(inputStream);
    
    
    System.out.println(data);
    System.out.println("nList of Skills: ");
    data.getSkills().stream().forEach(System.out::println);
    System.out.println("nList of Tutorials: ");
    data.getTutorials().stream().forEach(System.out::println);
}

Нарешті, коли ми друкуємо data, це виглядатиме приблизно так:

WebsiteContent{website='stackabuse', skills=[python, javascript, java, unix, machine learning, web development], tutorials=[{graphs={name=Graphs in Python - Theory and Implementation, tags=[python, data structures, algorithm], contributors=[David Landup, Dimitrije Stamenic, Jovana Ninkovic], last_updated=June 2022}}, {git={name=Git Essentials - Developer's Guide to Git, tags=[git], contributors=[David Landup, François Dupire, Jovana Ninkovic], last_updated=April 2022}}, {deep learning={name=Practical Deep Learning for Computer Vision with Python, tags=[python, machine learning, tensorflow, computer vision], contributors=[David Landup, Jovana Ninkovic], last_updated=October 2022}}], published=true}

List of Skills: 
python
javascript
java
unix
machine learning
web development

List of Tutorials: 
{graphs={name=Graphs in Python - Theory and Implementation, tags=[python, data structures, algorithm], contributors=[David Landup, Dimitrije Stamenic, Jovana Ninkovic], last_updated=June 2022}}
{git={name=Git Essentials - Developer's Guide to Git, tags=[git], contributors=[David Landup, François Dupire, Jovana Ninkovic], last_updated=April 2022}}
{deep learning={name=Practical Deep Learning for Computer Vision with Python, tags=[python, machine learning, tensorflow, computer vision], contributors=[David Landup, Jovana Ninkovic], last_updated=October 2022}}

Як ми бачимо, SnakeYaml успішно проаналізував і перетворив WebsiteContent об'єкта та зберіг спадщину та товариство с Tutorial об'єкт цілий.

Висновок

Оскільки файли YAML широко використовуються для даних DevOps і конфігурації, дуже корисно аналізувати та маніпулювати даними за допомогою коду.

SnakeYAML дозволяє нам легко керувати файлами YAML у нашому проекті Java, і для завантаження файлів YAML у наш проект або запису даних у файли YAML потрібно лише трохи коду. Крім того, SnakeYAML пропонує варіанти форматування, щоб ви могли налаштувати та персоналізувати його відповідно до наших потреб.

Часова мітка:

Більше від Stackabuse