介绍
Yaml 是之后最流行的数据序列化语言之一 JSON. 因此,它有时被称为 严格 超集 的 JSON。 它从一开始就是为人类交互和可读性而设计的,因此,它以其简单而闻名。 它的设计考虑了灵活性和可访问性,因此它适用于所有现代编程语言和用于编写配置文件的强大格式。 它还用于数据持久性、互联网消息传递、跨语言数据共享以及更多选项。
YAML 始于 2001 年,被称为“另一种标记语言“ 当时。 但后来它被注册为“YAML 不是标记语言“。 YAML 文件的基本结构是 地图. 它也被称为字典、散列(映射)或简单的基于我们选择使用的编程语言的对象。
YAML 文件中使用空格和缩进来表示嵌套。
备注: YAML 文件的缩进只能使用空格; 不允许使用制表符。 只要缩进始终如一,使用多少空格都没有关系。
YAML 语法
YAML 格式主要使用 3 种节点类型:
- 地图/字典:一个 地图 节点的内容是一个无序的集合 核心价值 节点 对, 要求每个键必须是不同的。 YAML 没有对节点施加进一步的限制。
- 数组/列表:安 排列 节点的内容是零个或多个节点的有序集合。 特别是,一个序列可能不止一次地包含同一个节点。 它甚至可能包含它自己。
- 文字 (字符串、数字、布尔值等):零个或多个的序列 Unicode字符 可以用来表示组成一个不透明数据 纯量 节点的内容。
在本文中,我们将专门研究如何将 YAML 数组内容转换为 Java 中的 List。 有很多可用的开源库,但其中最受欢迎的是 杰克逊 和 蛇YAML. 在本指南中,我们将使用 SnakeYaml 作为我们的库来解析 YAML 内容。
蛇药
蛇YAML 是一个 YAML 解析包,它为 YAML 文档序列化和反序列化提供高级 API。 SnakeYAML 的入口点是 Yaml
班级。 可以使用加载文档或 YAML 文件 load()
方法或批量通过 loadAll()
方法。 这些方法以字符串对象的形式获取真正的 YAML 数据以及 InputStreams
,这是遇到的典型文件类型。
鉴于 :
YAML 文件固有的结构,SnakeYAML 自然适用于 Java 地图,但我们也可以使用唯一的 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 文件中读取一个简单的数组快速开始。 假设我们的 Java 项目的资源文件夹中有一个包含以下数据的 yaml 文件:
- 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
包含一个 :
其中值为 排列. 所以数据仍将被加载为 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 文件 - 使用带有列表列表的映射映射很难直观地解析并且难以处理。 即使在最后一个我们只有两个嵌套列表的示例中——将它们作为列表处理也会变得相当冗长。
在这些情况下,最好创建一个可以映射到嵌套 YAML 数据的 POJO。让我们首先创建一个包含网站嵌套内容的示例 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
类对象,我们需要指定我们要将数据转换成的数据类型。 这 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 让我们可以轻松地管理 Java 项目中的 YAML 文件,并且只需要一点代码即可将 YAML 文件加载到我们的项目中或将数据写入 YAML 文件中。 此外,SnakeYAML 提供格式选择,因此您可以调整和个性化它以满足我们的需求。