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