Рубрики
Без рубрики

Чтение и запись файлов YAML на Java с помощью SnakeYaml

В этом уроке мы рассмотрим, как читать и записывать файлы YAML на Java с помощью SnakeYaml, популярной альтернативы Jackson.

Автор оригинала: Taimoor Choudhary.

Вступление

YAML расшифровывается как YAML-это не язык разметки, это язык сериализации данных, наиболее часто используемый для указания деталей конфигурации проекта. Основная мотивация YAML заключается в том, что он разработан в удобном для человека формате. С первого взгляда мы можем получить представление о свойствах и их соответствующих значениях, а также о взаимосвязи между свойствами, если она существует.

Поскольку файлы YAML в настоящее время часто используются, почти в каждом другом проекте мы сталкиваемся со сценарием, когда нам приходится управлять данными в файлах YAML с помощью нашего кода. Существует множество библиотек с открытым исходным кодом, доступных для обработки файлов YAML на Java.

Для достижения этой цели мы можем использовать любую из двух популярных библиотек: Jackson или SnakeYaml .

В этой статье мы сосредоточимся на Как читать и записывать файлы YAML на Java с помощью SnakeYaml .

Змеиный ям

SnakeYaml – это библиотека синтаксического анализа YAML с высокоуровневым API для сериализации и десериализации документов YAML.

Точкой входа для SnakeYaml является класс Yaml , аналогично тому, как класс ObjectMapper является точкой входа в Джексон .

Загрузка документов может быть выполнена для отдельных документов с помощью метода load() или в пакетном режиме с помощью метода loadAll () . Методы принимают Входной поток , который является обычным форматом для поиска файлов, а также Строковые объекты, содержащие допустимые данные YAML.

С другой стороны, мы можем сбрасывать() объекты Java в документы YAML с легкостью – где ключи/поля и значения отображаются в документе.

Естественно, SnakeYaml хорошо работает с Java Maps , учитывая структуру <ключ>:<значение> , однако вы также можете работать с пользовательскими объектами Java.

Если вы используете Maven, установите SnakeYaml, добавив следующую зависимость:


    org.yaml
    snakeyaml
    ${org.snakeyaml.version}

И если вы используете 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-проекта. Давайте сначала загрузим файл в качестве входного потока .

Затем мы создадим экземпляр Yaml , который является отправной точкой для использования библиотеки. Экземпляр Yaml знакомит нас с методами, такими как load () , которые позволяют нам читать и анализировать любой Входной поток , Считыватель или Строку с допустимыми данными YAML:

InputStream inputStream = new FileInputStream(new File("student.yml"));

Yaml yaml = new Yaml();
Map data = yaml.load(inputStream);
System.out.println(data);

Метод возвращает Java Карту , в которой имена свойств используются в качестве ключей против их соответствующих значений.

Обратите внимание , что значения в Карте имеют тип Объект , потому что в файле YAML – мы можем иметь наши данные в виде строковых значений, чисел или даже коллекций. Все это может быть помещено в Объект , поэтому оно включает в себя любое значение, которое мы могли бы ввести.

Если мы напечатаем наш данные объект, в который мы загрузили файл YAML, мы получим следующий результат:

{id=20, name=Bruce, year=2020, address=Gotham City, department=Computer Science}

Как вы можете видеть, свойства из файла YAML просто отображаются в виде пар ключ-значение в объекте карты java.

Давайте обновим наш файл 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 содержит коллекцию курсов , которая имеет несколько значений данных.

Чтобы прочитать обновленный файл 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}]
}

Элемент courses в файле YAML читается как ArrayList , где каждое значение в списке является Картой самим объектом.

Прочитайте объект YAML как пользовательский объект Java

Теперь, когда мы успешно использовали файл YAML в нашем Java-коде в виде простых пар ключ-значение, давайте загрузим тот же файл в качестве пользовательского объекта Java, что является гораздо более распространенным вариантом использования.

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Мы будем использовать следующие классы 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 courses;
    // Getters and setters
}

public class Course {
    private String name;
    private double credits;
    // Getters and setters
}

Мы загрузим данные в объект Student , где элемент courses из файла YAML будет преобразован в Список типа Курс .

Мы будем использовать тот же файл YAML, который мы использовали в предыдущем примере, и загрузим его в качестве входного потока :

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 , мы указываем тип данных, в который мы хотим преобразовать данные. Новый конструктор(Student.class) говорит SnakeYaml, чтобы он прочитал данные из файла YAML и сопоставил их с нашим объектом Student .

Сопоставление является простым, и имена атрибутов вашего объекта должны совпадать с именами атрибутов YAML ( курсы -> курсы ).

Это приводит к:

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 (Родительский класс Человек ) и связь с классом Курс нетронутыми.

Написание YAML с помощью SnakeYaml

Теперь, когда мы успешно прочитали файлы YAML в нашем Java-коде, давайте начнем записывать данные в файлы YAML с помощью нашего Java-проекта. Аналогично чтению документов YAML, мы можем записать простой Java Map и пользовательский объект Java в файл YAML.

Напишите Карту В YAML

Давайте сначала запишем простой объект Map в файл YAML:

Map dataMap = new HashMap<>();
dataMap.put("id", 19);
dataMap.put("name", "John");
dataMap.put("address", "Star City");
dataMap.put("department", "Medical");

Теперь давайте создадим новый объект PrintWriter , имея в виду выходной каталог, и дамп() карту данных , используя этот писатель.

Примечание: Метод dump() принимает любой |/Писатель :

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 не содержит значений в той же последовательности, в которой мы добавили их в наш объект Java Map , поскольку мы использовали HashMap , который не сохраняет порядок ввода.

Вы можете устранить эту проблему, используя вместо этого LinkedHashMap .

Напишите пользовательский объект Java в YAML

Теперь давайте попробуем сохранить наш Студент класс в формате 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 courseList = new ArrayList<>();
courseList.add(courseOne);
courseList.add(courseTwo);

student.setCourses(courseList);

Теперь давайте используем наш экземпляр Yaml с реализацией Writer для дампа() данных в файл:

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, сгенерированные нашим кодом, вы увидите, что в первом примере все данные были сброшены в одну строку, тогда как во втором примере значения Курс объекта записаны в одной строке каждый под элементом курсы.

Хотя оба сгенерированных выходных файла имеют допустимый синтаксис 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 . Теперь, когда мы используем функцию 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 .