Введение
YAML является одним из самых популярных языков сериализации данных после JSON. Поэтому его иногда называют строгий надстройка JSON. Он с самого начала был разработан для человеческого взаимодействия и удобочитаемости, поэтому он известен своей простотой. Он разработан с учетом гибкости и доступности, поэтому он работает со всеми современными языками программирования и мощным форматом для записи файлов конфигурации. Он также используется для сохранения данных, обмена сообщениями в Интернете, обмена данными на разных языках и многих других опций.
YAML был запущен в 2001 году и назывался «Еще один язык разметки" в то время. Но позже он был зарегистрирован как «YAML - это не язык разметки“. Базовая структура файла YAML представляет собой карта. Он также известен как словарь, хэш (карта) или просто объект на основе языка программирования, который мы решили использовать.
Пробелы и отступы используются в файлах YAML для обозначения вложенности.
Внимание: для отступов в файлах YAML можно использовать только пробелы; символы табуляции не допускаются. Пока отступ выполняется последовательно, не имеет значения, сколько пробелов используется.
Синтаксис YAML
Формат YAML в основном использует 3 типа узлов:
- Карты/Словари: карта содержимое узла представляет собой неупорядоченный набор ключ / значение узел пар, с требованием, чтобы каждый ключ был различен. Никаких дополнительных ограничений на узлы YAML не накладывает.
- Массивы / Списки: массив содержимое узла представляет собой упорядоченный набор из нуля или более узлов. В частности, последовательность может включать один и тот же узел более одного раза. Он может содержать даже самого себя.
- литералы (Строки, числа, логические значения и т. д.): последовательность из нуля или более Символы Юникод может использоваться для представления непрозрачных данных, составляющих скаляр содержимое узла.
В этой статье мы специально рассмотрим преобразование содержимого массива YAML в список в Java. Существует множество библиотек с открытым исходным кодом, но наиболее популярными из них являются Джексон и ЗмеяЯМЛ. В этом руководстве мы будем использовать SnakeYaml в качестве нашей библиотеки для анализа содержимого YAML.
ЗмеяЯмл
ЗмеяЯМЛ — это пакет синтаксического анализа YAML, который предлагает высокоуровневый API для сериализации и десериализации документов YAML. Точкой входа для SnakeYAML является Yaml
учебный класс. Документы или файлы YAML можно загрузить с помощью load()
метод или в пакетном режиме через loadAll()
метод. Методы принимают подлинные данные YAML в виде объектов String, а также InputStreams
, который является типичным типом файла, с которым можно столкнуться.
Учитывая :
структура, присущая файлам YAML, SnakeYAML, естественно, хорошо работает с Карты Явы, но мы также можем использовать уникальные Объекты 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. Учтите, что у нас есть файл yaml со следующими данными в папке ресурсов нашего проекта Java:
- One
- Two
- Three
- Four
Затем мы можем загрузить содержимое файла как InputStream
. Далее мы построим Yaml
экземпляр, который затем будет действовать как точка входа для доступа к библиотеке и объекту для программного представления содержимого файла YAML. 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
содержащий :
где значение является массив. Таким образом, данные будут по-прежнему загружаться как InputStream
как мы определили выше. Но data
должно быть определено как Map
of List
of String
s:
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
навыков и 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 + ''' +
'}';
}
}
Теперь мы снова можем загрузить данные из файла в виде InputStream
как мы делали раньше. Далее, когда мы создадим наш Yaml
class, нам нужно указать тип данных, в который мы хотим преобразовать данные. 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 предлагает варианты форматирования, поэтому вы можете настроить и персонализировать его в соответствии со своими потребностями.