YAML文件
YAML文件的定义
YAML (YAML Ain't Markup Language) 是一种轻量级的数据序列化格式,它的语法简单、易读、易写。YAML 文件通常以 .yml 或 .yaml 扩展名进行命名。
文件特点
- YAML 是一种“人类友好”的数据格式,它的语法结构简单、易于阅读和编写,使得 YAML 文件在可读性和可维护性方面比其他数据格式(如 JSON 或 XML)更具优势。
- YAML 文件支持多种数据类型,包括字符串、数字、布尔值、日期、时间、列表、对象等。它还支持引用、锚点、别名等特性,可以帮助减少文件的冗余度。
- 在 YAML 文件中,以“#”开头的行表示注释。注释可以出现在键值对或列表的任意一行,用于解释这些数据的含义或提供其他相关信息。
- YAML 文件可以嵌套和组合,这意味着在一个 YAML 文件中可以定义复杂的数据结构。例如,可以在一个列表中嵌套多个对象,或者在一个对象中嵌套多个列表。
- YAML 文件的解析和序列化非常方便,因为它可以很容易地转换为常见的编程语言数据结构,例如 Python 中的字典和列表、Java 中的 Map 和 List 等等。
总之,YAML 是一种优秀的数据格式,它的简洁易读性、灵活性和可扩展性使得它在许多场景下都是一个很好的选择。
YAML 文件基础语法
YAML 文件基础语法非常简单,主要由键值对和列表构成。键值对由键名和键值组成,用冒号分隔;列表由多个值组成,用短横线“-”表示。以下是一个基本的 YAML 文件示例:
# 注释
key1: value1
key2: value2
list:
- item1
- item2
在 YAML 文件中,以“#”开头的行表示注释,注释可以出现在任何位置。
YAML 文件数据类型
YAML 文件支持多种数据类型,包括字符串、数字、布尔值、日期、时间、列表、对象等。以下是一些常用的数据类型及其示例:
字符串
字符串可以使用单引号或双引号包裹,也可以不使用引号。如果字符串中包含特殊字符(如冒号、短横线等),则需要使用引号将其括起来。
str1: 'Hello, World!'
str2: "Hello, YAML!"
str3: Hello, YAML!
str4: 'a:b:c'
数字
数字可以是整数或浮点数,可以使用十进制、八进制、十六进制等表示法。
int1: 123
int2: -456
float1: 3.14
octal: 0o123
hex: 0x1a
布尔值
布尔值可以是 true 或 false。
bool1: true
bool2: false
日期和时间
日期和时间可以使用 ISO 8601 格式表示。
date: 2022-01-01
time: 10:30:00
datetime: 2022-01-01T10:30:00Z
列表
列表由多个值组成,用短横线“-”表示。
list:
- item1
- item2
- item3
对象
对象由多个键值对组成,用冒号“:”分隔。
person:
name: John
age: 30
hobbies:
- hiking
- reading
YAML 文件示例
以下是一个更复杂的 YAML 文件示例,展示了 YAML 文件的嵌套和组合特性:
# 注释
person:
name: John Smith
age: 30
address:
street: 123 Main St.
city: San Francisco
state: CA
zip: 12345
hobbies:
- hiking
- reading
- traveling
friends:
- name: Jane Doe
age: 28
address:
street: 456 Oak St.
city: New York
state: NY
zip: 67890
- name: Bob Johnson
age: 32
address:
street: 789 Pine St.
city: Los Angeles
state: CA
zip: 45678
这个 YAML 文件定义了一个人的信息,包括姓名、年龄、地址、爱好和朋友列表。其中,地址和朋友列表都是嵌套的对象,朋友列表中每个朋友也是一个嵌套的对象。
其它特性
YAML 还支持引用、锚点和别名等特性,这些特性可以帮助减少文件的冗余度。
引用
在 YAML 文件中,可以使用“&”字符定义一个引用,在其他位置使用“*”字符引用这个引用。引用可以是一个键、一个值或者一个对象。
# 定义引用
person: &person
name: John Smith
age: 30
# 使用引用
person1: *person
person2: *person
在这个示例中,我们定义了一个名为“person”的引用,它包含一个人的姓名和年龄。然后,我们使用“*person”在两个不同的位置引用了这个引用,这样就可以避免重复定义相同的数据。
锚点和别名
在 YAML 文件中,可以使用“&”字符定义一个锚点,在其他位置使用“*”字符引用这个锚点。锚点和引用的不同之处在于,锚点是一个对象或列表中的一部分,而引用是一个独立的键值对或值。
# 定义锚点
person:
name: John Smith
age: 30
address: &address
street: 123 Main St.
city: San Francisco
state: CA
zip: 12345
# 使用别名
person1:
<<: *person
address: *address
在这个示例中,我们定义了一个名为“address”的锚点,它包含一个人的地址信息。然后,我们在一个新的对象中使用“<<: *person”将“person”对象的所有键值对复制到这个对象中,并在“address”键使用“*address”引用了锚点。这样一来,我们就可以避免重复定义相同的数据,同时还可以保持 YAML 文件的简洁性和可读性。
差不多了解语法之后,可以进行操作了
Java读取YAML文件
和property与XML不同,Java并没有自带的处理yml的库,因此需要引入第三方库GitHub - snakeyaml,ps: 我看见这个是springboot也在用的库,所以推荐给大家。
SnakeYAML 是一个 Java 库,用于解析和生成 YAML 格式的数据。它可以将 YAML 格式的数据转换为 Java 对象,也可以将 Java 对象转换为 YAML 格式的数据。以下是使用 SnakeYAML 的基本步骤:
- 添加 SnakeYAML 依赖
首先,需要将 SnakeYAML 依赖添加到项目中。可以通过 Maven 或 Gradle 等构建工具来添加依赖,例如:
<!-- Maven 依赖 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.29</version>
</dependency>
- 创建 Yaml 对象
接下来,需要创建 Yaml 对象。Yaml 对象是 SnakeYAML 库的核心类,用于解析和生成 YAML 格式的数据。可以使用默认构造函数创建 Yaml 对象,例如:
Yaml yaml = new Yaml();
- 解析 YAML 数据
要解析 YAML 数据,可以使用 Yaml 对象的 load() 方法。load() 方法接受一个输入流或字符串作为参数,可以将 YAML 数据解析为 Java 对象或 Map 对象。例如:
InputStream inputStream = new FileInputStream("example.yml");
// 将数据读进map
Map<String, Object> data = yaml.load(inputStream);
在这个示例中,我们创建了一个 FileInputStream 对象来读取名为 example.yml 的 YAML 文件,然后调用 Yaml 对象的 load() 方法将其解析为一个 Map 对象。
完整代码
package property;
import org.yaml.snakeyaml.Yaml;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Map;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Yaml yaml = new Yaml();
InputStream inputStream = new FileInputStream("D:\works\untitled2\src\main\java\property\property.yml");
Map<String, Object> data = yaml.load(inputStream);
for (String s : data.keySet()) {
System.out.println(data.get(s));
}
}
}
Java修改yml文件
在使用 SnakeYAML 将 YAML 数据解析为 Map 对象之后,可以使用类似于操作普通 Map 对象的方式来修改其中的数据。
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Yaml yaml = new Yaml();
Map<String, Object> data = new LinkedHashMap<>();
data.put("name", "Alice");
data.put("age", 30);
Map<String, String> address = new LinkedHashMap<>();
address.put("street", "123 Main St");
address.put("city", "Anytown");
address.put("state", "CA");
address.put("zip", "12345");
data.put("address", address);
try {
FileWriter writer = new FileWriter("D:\works\untitled2\src\main\java\property\after.yml");
// 默认是流式形式输出文件
yaml.dump(data, writer);
writer.close();
System.out.println("YAML data written to file.");
} catch (IOException e) {
e.printStackTrace();
}
data.put("name", "Bob");
data.put("age", 40);
address.put("zip", "67890");
try {
FileWriter writer = new FileWriter("example.yml");
DumperOptions options = new DumperOptions();
// 将输出格式换为块级形式
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
// 新建yml对象
yaml = new Yaml(options);
yaml.dump(data, writer);
writer.close();
System.out.println("YAML data updated in file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
知识点补充
DumperOptions 是 SnakeYAML 用于控制 YAML 数据输出格式的类,可以通过它来设置如何将数据转换为 YAML 格式。
在上述代码中,我们创建了一个 DumperOptions 对象,并使用 setDefaultFlowStyle() 方法来设置 YAML 数据的块式格式。在 YAML 中,块式格式使用缩进来表示层次关系,而流式格式使用花括号和逗号来表示。例如,下面是一个包含一个 Map 对象的 YAML 数据的块式格式和流式格式:
块式格式:
person:
name: Alice
age: 30
address:
street: 123 Main St
city: Anytown
state: CA
zip: 12345
流式格式: (json)
person: {name: Alice, age: 30, address: {street: 123 Main St, city: Anytown, state: CA, zip: 12345}}
在实际应用中,可以根据需要选择合适的格式来输出 YAML 数据。如果数据包含较多的嵌套层次或较多的属性,那么块式格式可能更易于阅读和维护。如果数据比较简单或较少,那么流式格式可能更加紧凑和简洁。
知识点补充
只有在特殊情况下,YAML解析器才支持用=号连接列表元素,例如:
- Spring Cloud Gateway 的
predicates配置 - Spring Boot 的
spring.sql.init.platform配置
routes:
- id: service-hosp
uri: lb://service-hosp
predicates:
- Path=/*/hosp/**
- id: service-cmn
uri: lb://service-cmn
- Path=/*/cmn/**
- id: service-user
uri: lb://service-user
- Path=/*/user/**