Convertir un tableau YAML en liste Java avec SnakeYAML

Introduction

YAML est l'un des langages de sérialisation de données les plus populaires après JSON. Par conséquent, il est parfois appelé comme un strict sur-ensemble de JSON. Il a été conçu pour l'interaction humaine et la lisibilité dès le début, c'est pourquoi il est connu pour sa simplicité. Il est conçu dans un souci de flexibilité et d'accessibilité, il fonctionne donc avec tous les langages de programmation modernes et un format puissant pour l'écriture de fichiers de configuration. Il est également utilisé pour la persistance des données, la messagerie Internet, le partage de données multilingues et bien d'autres options.

YAML a été lancé en 2001 et s'appelait "Encore un autre langage de balisage" à ce moment-là. Mais plus tard, il a été déposé sous le nom de "YAML n'est pas un langage de balisage“. La structure de base d'un fichier YAML est un Localisation. Il est également connu sous le nom de dictionnaire, de hachage (carte) ou simplement basé sur un objet selon le langage de programmation que nous choisissons d'utiliser.

Les espaces blancs et l'indentation sont utilisés dans les fichiers YAML pour indiquer l'imbrication.

Notes : Seuls les espaces peuvent être utilisés pour l'indentation dans les fichiers YAML ; les caractères de tabulation ne sont pas autorisés. Tant que l'indentation est effectuée de manière cohérente, peu importe le nombre d'espaces utilisés.

Syntaxe YAML

Un format YAML utilise principalement 3 types de nœuds :

  • Cartes/Dictionnaires: Un Localisation le contenu du nœud est une collection non ordonnée de valeur clé nœud paires, avec l'exigence que chaque clé soit distincte. Aucune autre limitation n'est imposée aux nœuds par YAML.
  • Tableaux/Listes: Une tableau le contenu du nœud est une collection ordonnée de zéro ou plusieurs nœuds. Une séquence peut inclure plus d'une fois le même nœud, notamment. Il peut même contenir lui-même.
  • Littéraux (Chaînes, nombres, booléens, etc.) : une séquence de zéro ou plus Caractères Unicode peut être utilisé pour représenter les données opaques qui composent un scalaire contenu du nœud.

Dans cet article, nous examinerons spécifiquement la conversion du contenu d'un tableau YAML en une liste en Java. Il existe de nombreuses bibliothèques open source, mais les plus populaires d'entre elles sont Jackson et de SerpentYAML. Dans ce guide, nous utiliserons SnakeYaml comme bibliothèque pour analyser le contenu YAML.

SerpentYaml

SerpentYAML est un package d'analyse YAML qui offre une API de haut niveau pour la sérialisation et la désérialisation de documents YAML. Le point d'entrée de SnakeYAML est le Yaml classer. Les documents ou les fichiers YAML peuvent être chargés à l'aide de load() méthode ou en batch via la loadAll() méthode. Les méthodes prennent des données YAML authentiques sous la forme d'objets String ainsi que InputStreams, qui est un type de fichier typique à rencontrer.

Compte tenu du : structure innée aux fichiers YAML, SnakeYAML fonctionne naturellement bien avec Cartes Java, mais on peut aussi utiliser unique Objets Java.

Pour inclure la bibliothèque dans notre projet, ajoutez la dépendance suivante à votre pom.xml fichier:

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

Ou, si vous utilisez Gradle:

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

Lire un tableau YAML simple

Commençons rapidement par lire un tableau simple à partir d'un fichier YAML. Considérez que nous avons un fichier yaml avec les données suivantes dans le dossier des ressources de notre projet Java :

- One
- Two
- Three
- Four

Ensuite, nous pouvons charger le contenu du fichier en tant que InputStream. Ensuite, nous allons construire le Yaml instance qui servira alors de point d'entrée pour accéder à la bibliothèque et l'objet pour représenter le contenu du fichier YAML par programmation. La load() nous permet de lire et d'analyser n'importe quel InputStream avec des données YAML valides :

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

La méthode renverra un Java List de données de chaîne. Si nous imprimons le data alors cela donnera le résultat suivant :

[One, Two, Three, Four]

Lire un tableau groupé YAML

Parfois, nous aimerions définir un tableau de contenu par rapport à une clé donnée. C'est ce qu'on appelle le regroupement de tableaux dans un nœud de carte YAML. Un exemple de YAML de ce type ressemble à ceci :

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

Cela peut être considéré comme Java Map contenant un : où la valeur est un tableau. Ainsi, les données seront toujours chargées comme InputStream comme nous l'avons défini plus haut. Mais le data doit être défini comme 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);
}

Maintenant, si nous lisons notre data, cela ressemblerait à ceci :

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

Lecture d'un tableau multiligne de tableaux YAML

Parfois, nous rencontrons un fichier YAML contenant des données contenant un tableau de tableaux. Par exemple, nous regroupons les cours et les représentons sous forme de tableau de tableaux comme ci-dessous :

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

Cela peut être analysé comme Java Map of List of List of String. Nous pouvons à nouveau charger le InputStream comme nous l'avons fait plus tôt. Mais les données seront chargées comme ci-dessous :

Consultez notre guide pratique et pratique pour apprendre Git, avec les meilleures pratiques, les normes acceptées par l'industrie et la feuille de triche incluse. Arrêtez de googler les commandes Git et en fait apprendre il!

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);
}

Donc, si nous imprimons le data, cela ressemblerait à quelque chose comme ci-dessous:

{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

Lecture d'un contenu YAML imbriqué complexe en tant que Java Bean

Nous avons vu comment nous pouvons gérer le contenu de type tableau séparément, mais avec des fichiers YAML imbriqués complexes - avoir une carte de cartes avec des listes de listes est difficile à analyser intuitivement et difficile à gérer. Même dans le dernier exemple où nous n'avions que deux listes imbriquées - les traiter comme des listes devient assez verbeux.

Dans ces cas, il est préférable de créer un POJO qui peut être mappé sur les données YAML imbriquées. Commençons par créer un exemple de YAML contenant le contenu imbriqué d'un site Web :

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

Nous devons définir une classe Java parent WebsiteContent qui consistera à List de compétences et une List of Map de tutoriels qui contiendront à nouveau des listes de tags et de contributeurs :

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 + ''' +
                '}';
    }
}

Maintenant, nous pouvons à nouveau charger les données du fichier comme InputStream comme nous l'avons fait plus tôt. Ensuite, lorsque nous créons notre Yaml objet de classe, nous devons spécifier le type de données dans lequel nous voulons convertir les données. La new Constructor(WebsiteContent.class) dit à SnakeYAML de lire les données du fichier YAML le mapper à notre WebsiteContent objet.

Le mappage est simple et les noms de nos attributs d'objet doivent correspondre aux noms des attributs 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);
}

Enfin, lorsque nous imprimons le data, cela ressemblerait à quelque chose comme ci-dessous:

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}}

Comme nous pouvons le voir, SnakeYaml a analysé et converti avec succès le WebsiteContent objet et a conservé l'héritage et l'association avec Tutorial objet intact.

Conclusion

Comme les fichiers YAML sont largement utilisés pour DevOps et les données liées à la configuration, il est très utile d'analyser et de manipuler les données à l'aide de code.

SnakeYAML nous permet de gérer facilement les fichiers YAML dans notre projet Java, et il ne nécessite qu'un peu de code pour charger des fichiers YAML dans notre projet ou écrire des données dans des fichiers YAML. De plus, SnakeYAML propose des choix de formatage afin que vous puissiez l'ajuster et le personnaliser en fonction de nos besoins.

Horodatage:

Plus de Stackabuse