Вступление
YAML означает YAML Ain't Markup Language, это язык сериализации данных, наиболее часто используемый для указания деталей конфигурации проекта. Основная мотивация YAML заключается в том, что он разработан в удобном для человека формате. С первого взгляда мы можем получить представление о свойствах и их соответствующих значениях, а также о взаимосвязи между свойствами, если она существует.
Поскольку файлы YAML сейчас используются часто, почти в каждом другом проекте мы сталкиваемся со сценарием, когда нам нужно управлять данными в файлах YAML через наш код. Для обработки файлов YAML в Java доступно множество библиотек с открытым исходным кодом.
Для этого мы можем использовать любую из двух популярных библиотек: Jackson или SnakeYAML .
В этой статье мы сосредоточимся на том, как читать и писать файлы YAML на Java с помощью SnakeYAML .
ЗмеяYAML
SnakeYAML - это библиотека анализа YAML с высокоуровневым API для сериализации и десериализации документов YAML.
Точка входа для SnakeYAML является Yaml
класс, подобно тому , как
ObjectMapper
класс является точкой входа в Джексон.
Загрузка документов может выполняться для отдельных документов с помощью
load()
или в пакетном режиме с помощью loadAll()
. Методы принимают
InputStream
, который является распространенным форматом для поиска
файлов, а также String
содержащие допустимые данные YAML.
С другой стороны, мы можем dump()
Java-объекты в документы YAML - где
ключи / поля и значения отображаются в документ.
Естественно, SnakeYAML хорошо работает с Java
Maps , учитывая структуру
<key>:<value>
, однако вы также можете работать с пользовательскими
объектами Java.
Если вы используете Maven, установите SnakeYAML, добавив следующую зависимость:
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${org.snakeyaml.version}</version>
</dependency>
А если вы используете Gradle , установить SnakeYAML так же просто, как включить в свой файл Gradle следующее:
compile group: 'org.yaml', name: 'snakeyaml', version: '{version}'
Вы можете проверить последнюю версию библиотеки в центральном репозитории Maven .
Чтение YAML с помощью SnakeYAML
SnakeYAML позволяет вам читать файл YAML в простой Map
или
анализировать файл и преобразовывать его в пользовательский объект Java.
В зависимости от ваших требований вы можете решить, в каком формате вы
хотите читать свои файлы YAML. Давайте посмотрим на оба подхода.
Чтение файла YAML как карты на Java
Начнем с чтения простого файла YAML как набора пар ключ-значение. Файл, который мы будем читать, будет содержать следующие данные:
id: 20
name: Bruce
year: 2020
address: Gotham City
department: Computer Science
Предположим, у нас есть этот YAML в папке ресурсов нашего Java-проекта.
Давайте сначала загрузим файл как InputStream
Затем мы Yaml
экземпляр Yaml, который является точкой входа в
использование библиотеки. Yaml
знакомит нас с такими методами, как
load()
которые позволяют нам читать и анализировать любой
InputStream
, Reader
или String
с действительными данными YAML:
InputStream inputStream = new FileInputStream(new File("student.yml"));
Yaml yaml = new Yaml();
Map<String, Object> data = yaml.load(inputStream);
System.out.println(data);
Метод возвращает Map
Java, в которой имена свойств используются в
качестве ключей к их соответствующим значениям.
Обратите внимание, что значения на Map
имеют тип Object
, потому что
в файле YAML мы можем иметь наши данные в виде строковых значений, чисел
или даже коллекций. Все это может быть помещено в Object
поэтому он
включает в себя любое значение, которое мы можем ввести.
Если мы напечатаем наш data
в который мы загрузили файл YAML, мы
получим следующий результат:
{id=20, name=Bruce, year=2020, address=Gotham City, department=Computer Science}
Как видите, свойства из файла YAML просто отображаются как пары ключ-значение в объекте Java Map.
Давайте обновим наш YAML-файл, чтобы он также содержал данные коллекции. YAML-файл обновления выглядит так:
id: 20
name: Bruce
year: 2020
address: Gotham City
department: Computer Science
courses:
- name: Algorithms
credits: 6
- name: Data Structures
credits: 5
- name: Design Patterns
credits: 3
Теперь наш файл YAML содержит коллекцию courses
с несколькими
значениями данных.
Чтобы прочитать обновленный файл YAML, нет необходимости обновлять наш
код Java. Наш предыдущий код сможет успешно загрузить файл YAML в наш
объект Map
После прочтения файла результат будет:
{
id=20, name=Bruce, year=2020, address=Gotham City, department=Computer Science,
courses=[{name=Algorithms, credits=6}, {name=Data Structures, credits=5}, {name=Design Patterns, credits=3}]
}
Элемент курсов в файле YAML читается как ArrayList
где каждое значение
в списке является самим объектом Map
Чтение объекта YAML как настраиваемого объекта Java
Теперь, когда мы успешно использовали YAML-файл в нашем Java-коде в виде простых пар ключ-значение, давайте загрузим тот же файл, что и пользовательский Java-объект, что является гораздо более распространенным вариантом использования.
Мы будем использовать следующие классы Java для загрузки данных из наших файлов YAML:
public class Person {
private long id;
private String name;
private String address;
// Getters and setters
}
public class Student extends Person {
private int year;
private String department;
private List<Course> courses;
// Getters and setters
}
public class Course {
private String name;
private double credits;
// Getters and setters
}
Мы загрузим данные в Student
, где элемент курсов из файла YAML будет
преобразован в List
типа Course
.
Мы будем использовать тот же файл YAML, который мы использовали в
предыдущем примере, и загрузим его как InputStream
:
InputStream inputStream = new FileInputStream(new File("student_with_courses.yml"));
Yaml yaml = new Yaml(new Constructor(Student.class));
Student data = yaml.load(inputStream);
System.out.println(data);
Теперь, когда мы создаем наш Yaml
, мы указываем тип данных, в который
мы хотим преобразовать данные. new Constructor(Student.class)
сообщает
SnakeYAML читать данные из файла YAML, сопоставляя их с нашим объектом
Student
Сопоставление простое, и имена атрибутов вашего объекта должны совпадать
с именами атрибутов YAML ( courses
-> courses
).
Это приводит к:
Student[Person[id=20, name='Bruce', address='Gotham City'], year=2020, department='Computer Science', courses=[Course[name='Algorithms', credits=6.0], Course[name='Data Structure', credits=5.0], Course[name='Design patters', credits=3.0]]]
Как вы можете видеть, SnakeYAML успешно создал Student
, сохранив при
этом Student
(родительский класс Person
) и связь с классом Course
Написание YAML с помощью SnakeYAML
Теперь, когда мы успешно прочитали файлы YAML в нашем коде Java, давайте
приступим к записи данных в файлы YAML с помощью нашего проекта Java.
Подобно чтению документов YAML, мы можем записать простую Map
Java и
пользовательский объект Java в файл YAML.
Записать карту в YAML
Давайте сначала напишем простой Map
в файл YAML:
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", 19);
dataMap.put("name", "John");
dataMap.put("address", "Star City");
dataMap.put("department", "Medical");
Теперь давайте создадим новый PrintWriter
с учетом выходного каталога
и dump()
dataMap
используя этот писатель.
Примечание. Метод dump()
принимает любой
Writer
:
PrintWriter writer = new PrintWriter(new File("./src/main/resources/student_output.yml"));
Yaml yaml = new Yaml();
yaml.dump(dataMap, writer);
В результате получается файл, содержащий:
{address: Star City, name: John, id: 19, department: Medical}
Примечание: выходной файл YAML не имеет значений в той же
последовательности, в которой мы добавляли их в наш Map
, поскольку мы
использовали HashMap
который не сохраняет порядок ввода.
Вы можете решить эту проблему, используя вместо этого LinkedHashMap
Записать пользовательский объект Java в YAML
Теперь давайте попробуем сохранить наш Student
в формате YAML в
выходном файле. Для этого мы будем использовать следующий код для
настройки объекта Student
Student student = new Student();
student.setId(21);
student.setName("Tim");
student.setAddress("Night City");
student.setYear(2077);
student.setDepartment("Cyberware");
Course courseOne = new Course();
courseOne.setName("Intelligence");
courseOne.setCredits(5);
Course courseTwo = new Course();
courseTwo.setName("Crafting");
courseTwo.setCredits(2);
List<Course> courseList = new ArrayList<>();
courseList.add(courseOne);
courseList.add(courseTwo);
student.setCourses(courseList);
Теперь давайте используем наш экземпляр Yaml
с реализацией Writer
dump()
данных в файл:
PrintWriter writer = new PrintWriter(new File("./src/main/resources/student_output_bean.yml"));
Yaml yaml = new Yaml();
yaml.dump(student, writer);
Это приводит к:
!!model.Student
address: Night City
courses:
- {credits: 5.0, name: Intelligence}
- {credits: 2.0, name: Crafting}
department: Cyberware
id: 21
name: Tim
year: 2077
Если вы внимательно посмотрите на выходные файлы YAML, сгенерированные
нашим кодом, вы увидите, что в первом примере все данные были сброшены в
одну строку, тогда как во втором примере Course
записываются в одну
строку каждый под элементом курсов.
Хотя оба сгенерированных выходных файла имеют допустимый синтаксис YAML,
если вы хотите создать файл YAML в более часто используемом формате, где
каждое значение записывается в одной строке и нет скобок, вы можете
настроить DumperOptions
и передать его в конструктор Yaml
DumperOptions options = new DumperOptions();
options.setIndent(2);
options.setPrettyFlow(true);
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(options);
Здесь мы указали отступ и поток документов YAML с DumperOptions
объекта DumperOptions. Теперь, когда мы используем функцию dump
Yaml
мы получим вывод в другом формате:
!!model.Student
address: Night City
courses:
- credits: 5.0
name: Intelligence
- credits: 2.0
name: Crafting
department: Cyberware
id: 21
name: Tim
year: 2077
Заключение
Поскольку файлы YAML используются все чаще, особенно для указания свойств проекта и метаданных сборки и развертывания, становится все более полезным иметь возможность обрабатывать их с помощью кода.
С помощью SnakeYAML мы можем легко управлять файлами YAML в нашем проекте Java, а минимальный объем кода используется либо для загрузки файлов YAML в наш проект, либо для записи данных в файлы YAML. SnakeYAML также предоставляет параметры форматирования, так что вы можете настраивать их под свои нужды.
Исходный код примера кода можно найти на GitHub .