Konverter YAML Array til Java List med SnakeYAML

Introduktion

YAML er et af de mest populære dataserialiseringssprog efter JSON. Derfor kaldes det nogle gange som en streng supersæt af JSON. Den er designet til menneskelig interaktion og læsbarhed lige fra begyndelsen, og derfor er den kendt for sin enkelhed. Det er designet med fleksibilitet og tilgængelighed i tankerne, så det fungerer med alle moderne programmeringssprog og et kraftfuldt format til at skrive konfigurationsfiler. Det bruges også til datapersistens, internetmeddelelser, datadeling på tværs af sprog og mange flere muligheder.

YAML blev startet i 2001 og blev betegnet som "Endnu et Markup Language" på det tidspunkt. Men senere blev det varemærket som "YAML Ain't Markup Language“. Den grundlæggende struktur af en YAML-fil er en kort. Det er også kendt som en ordbog, hash(map) eller blot objektbaseret på det programmeringssprog, som vi vælger at bruge.

Mellemrum og indrykning bruges i YAML-filer til at angive indlejring.

Bemærk: Kun mellemrum må bruges til indrykning i YAML-filer; tabulatortegn er ikke tilladt. Så længe indrykningen udføres konsekvent, er det ligegyldigt, hvor mange pladser der bruges.

YAML syntaks

Et YAML-format bruger primært 3 nodetyper:

  • Kort/ordbøger: A kort nodes indhold er en uordnet samling af nøgle/værdi node par, med krav om, at hver nøgle skal være særskilt. Ingen yderligere begrænsninger pålægges noderne af YAML.
  • Arrays/lister: An matrix nodes indhold er en ordnet samling af nul eller flere noder. En sekvens kan især omfatte den samme node mere end én gang. Det kan endda indeholde sig selv.
  • konstanter (Strenge, tal, boolean osv.): En sekvens på nul eller mere Unicode-tegn kan bruges til at repræsentere de uigennemsigtige data, der udgør en skalar nodens indhold.

I denne artikel vil vi specifikt tage et kig på at konvertere YAML-arrayindhold til en liste i Java. Der er masser af open source-biblioteker tilgængelige, men de mest populære af dem er Jackson , SnakeYAML. I denne guide vil vi bruge SnakeYaml som vores bibliotek til at analysere YAML-indholdet.

SnakeYaml

SnakeYAML er en YAML-parsing-pakke, der tilbyder en API på højt niveau til YAML-dokumentserialisering og deserialisering. Indgangspunktet for SnakeYAML er Yaml klasse. Dokumenterne eller YAML-filerne kan indlæses vha load() metode eller i batch via loadAll() metode. Metoderne tager ægte YAML-data i form af String-objekter såvel som InputStreams, som er en typisk filtype at støde på.

På grund af : struktur medfødt til YAML-filer, fungerer SnakeYAML naturligvis godt med Java kort, men vi kan også bruge unikke Java objekter.

For at inkludere biblioteket i vores projekt skal du tilføje følgende afhængighed til din pom.xml fil:

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

Eller, hvis du bruger Gradle:

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

Læsning af et simpelt YAML-array

Lad os hurtigt starte med at læse et simpelt array fra en YAML-fil. Overvej, at vi har en yaml-fil med følgende data i vores Java-projekts ressourcemappe:

- One
- Two
- Three
- Four

Så kan vi indlæse filindholdet som en InputStream. Dernæst vil vi konstruere Yaml forekomst, som derefter vil fungere som et indgangspunkt for at få adgang til biblioteket og objektet for at repræsentere YAML-filens indhold programmatisk. Det load() metode giver os mulighed for at læse og parse evt InputStream med gyldige YAML-data:

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

Metoden returnerer en Java List af strengdata. Hvis vi udskriver data så vil det give følgende resultat:

[One, Two, Three, Four]

Læsning af et YAML Grouped Array

Nogle gange vil vi gerne definere en række indhold mod en given nøgle. Dette kaldes gruppering af arrays i en YAML-kortnode. Et eksempel på YAML af en sådan art ser ud som nedenfor:

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

Dette kan betragtes som Java Map indeholdende en : hvor værdien er an matrix. Så dataene vil stadig blive indlæst som InputStream som vi definerede ovenfor. Men data skal defineres som 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);
}

Hvis vi nu læser vores data, det ville se sådan ud:

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

Læsning af en YAML Multi-Line Array af Arrays

Nogle gange støder vi på en YAML-fil med data, der indeholder en række arrays. For eksempel grupperer vi kurserne og repræsenterer dem som en række af arrays som nedenfor:

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

Dette kan parses som Java Map of List of List of String. Vi kan igen indlæse InputStream som vi gjorde tidligere. Men dataene indlæses som nedenfor:

Tjek vores praktiske, praktiske guide til at lære Git, med bedste praksis, brancheaccepterede standarder og inkluderet snydeark. Stop med at google Git-kommandoer og faktisk lærer det!

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

Så hvis vi udskriver data, ville det se nogenlunde ud som nedenfor:

{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

Læsning af et komplekst indlejret YAML-indhold som Java Bean

Vi så, hvordan vi kan håndtere indholdet af matrixtypen separat, men med komplekse indlejrede YAML-filer – at have et kort over kort med lister over lister er svært at analysere intuitivt og svært at håndtere. Selv i det sidste eksempel, hvor vi kun havde to indlejrede lister – bliver håndteringen af ​​dem som lister ret omfattende.

I disse tilfælde er det bedst at oprette en POJO, der kan tilknyttes de indlejrede YAML-data. Lad os først oprette et eksempel på YAML, der indeholder det indlejrede indhold af et websted:

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

Vi skal definere en overordnet Java-klasse WebsiteContent der vil bestå af List af færdigheder og en List of Map af selvstudier, som igen vil indeholde lister over tags og bidragydere:

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

Nu kan vi igen indlæse data fra filen som InputStream som vi gjorde tidligere. Næste når vi skaber vores Yaml klasseobjekt, skal vi angive den datatype, vi vil caste dataene ind i. Det new Constructor(WebsiteContent.class) fortæller SnakeYAML at læse dataene fra YAML-filen, kortlægge det til vores WebsiteContent objekt.

Kortlægningen er ligetil, og navnene på vores objektattributter skal matche navnene på YAML-attributterne.

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

Endelig, når vi udskriver data, ville det se nogenlunde ud som nedenfor:

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

Som vi kan se, har SnakeYaml med succes analyseret og konverteret WebsiteContent genstand og beholdt arven og foreningen med Tutorial objekt intakt.

Konklusion

Da YAML-filer bruges meget til DevOps og konfigurationsrelaterede data, er det ganske nyttigt at parse og manipulere dataene ved hjælp af kode.

SnakeYAML giver os mulighed for at administrere YAML-filer i vores Java-projekt med lethed, og det kræver kun en lille smule kode for at indlæse YAML-filer i vores projekt eller skrive data til YAML-filer. Derudover tilbyder SnakeYAML formateringsvalg, så du kan justere og tilpasse det, så det passer til vores behov.

Tidsstempel:

Mere fra Stablemisbrug