המר את מערך YAML ל-Java List עם SnakeYAML

מבוא

ימל היא אחת מהשפות הפופולריות ביותר להסדרת נתונים לאחר JSON. לכן, זה נקרא לפעמים בתור a קַפְּדָנִי סופר-סט של JSON. הוא תוכנן לאינטראקציה אנושית ולקריאה כבר מההתחלה, ומכאן שהוא ידוע בפשטותו. הוא תוכנן מתוך מחשבה על גמישות ונגישות, כך שהוא עובד עם כל שפות התכנות המודרניות ופורמט רב עוצמה לכתיבת קובצי תצורה. הוא משמש גם להתמדה בנתונים, העברת הודעות באינטרנט, שיתוף נתונים בין שפות ואפשרויות רבות נוספות.

YAML הוקמה בשנת 2001 והיא כונתה "שפת סימון נוספת" באותו זמן. אבל מאוחר יותר זה היה סימן מסחרי כ"YAML Ain't Markup Language". המבנה הבסיסי של קובץ YAML הוא א מַפָּה. זה ידוע גם בתור מילון, hash (מפה) או פשוט מבוסס אובייקט על שפת התכנות שבה אנו בוחרים להשתמש.

רווח לבן והזחה משמשים בקובצי YAML לציון קינון.

הערות: ניתן להשתמש רק ברווחים להזחה בקבצי YAML; תווי טאבים אינם מותרים. כל עוד ההזחה מתבצעת באופן עקבי, זה לא משנה כמה חללים מנוצלים.

תחביר YAML

פורמט YAML משתמש בעיקר בשלושה סוגי צמתים:

  • מפות/מילון: מַפָּה התוכן של node הוא אוסף לא מסודר של ערך מפתח צומת זוגות, עם הדרישה שכל מפתח חייב להיות נבדל. לא מוטלות מגבלות נוספות על הצמתים על ידי YAML.
  • מערכים/רשימות: מערך התוכן של הצומת הוא אוסף מסודר של אפס צמתים או יותר. רצף עשוי לכלול את אותו צומת יותר מפעם אחת, במיוחד. הוא עשוי להכיל אפילו את עצמו.
  • מילוליות (מחרוזות, מספרים, בוליאני וכו'): רצף של אפס או יותר תווים של Unicode ניתן להשתמש כדי לייצג את הנתונים האטומים המרכיבים את a סקלר התוכן של הצומת.

במאמר זה, נבחן באופן ספציפי את המרת תוכן מערך YAML לרשימה ב-Java. יש הרבה ספריות קוד פתוח זמינות, אבל הפופולריות שבהן הן ג'קסון ו SnakeYAML. במדריך זה, נשתמש ב-SnakeYaml כספרייה שלנו כדי לנתח את תוכן YAML.

SnakeYaml

SnakeYAML היא חבילת ניתוח YAML המציעה ממשק API ברמה גבוהה עבור הסדרת מסמכי YAML וסידריאליזציה. נקודת הכניסה ל-SnakeYAML היא Yaml מעמד. ניתן לטעון את המסמכים או קבצי YAML באמצעות load() שיטה או באצווה באמצעות ה loadAll() שיטה. השיטות לוקחות נתונים מקוריים של YAML בצורה של אובייקטי מחרוזת וכן InputStreams, שהוא סוג קובץ טיפוסי להיתקל בו.

בהינתן : מבנה המולד לקבצי YAML, SnakeYAML עובד היטב איתו מפות ג'אווה, אך אנו עשויים להשתמש גם ב- unique אובייקטי 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 המכיל a : כאשר הערך הוא an מערך. אז הנתונים עדיין ייטענו כ InputStream כפי שהגדרנו למעלה. אבל ה data חייב להיות מוגדר כ 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);
}

עכשיו אם אנחנו קוראים את שלנו 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 מציע אפשרויות עיצוב כך שתוכל להתאים ולהתאים אותו לצרכים שלנו.

בול זמן:

עוד מ Stackabuse