YAML 详解与实战

Posted 陈皮的JavaLib

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了YAML 详解与实战相关的知识,希望对你有一定的参考价值。

我是陈皮,一个在互联网 Coding 的 ITer,个人微信公众号「陈皮的JavaLib」关注第一时间阅读最新技术文章。

文章目录

YAML 简介

YAML,即 YAML Ain’t a Markup Language(YAML 不是一种标记语言)的递归缩写。YAML 其实意思是 Yet Another Markup Language(仍是一种标记语言)。它主要强度这种语言是以数据为中心,而不是以标记为中心,而像 XML 语言就使用了大量的标记。

YAML 可读性高,易于理解,用来表达数据序列化的格式。它的语法和其他高级语言类似,还可以简单表达数组、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件。

YAML 配置文件后缀为.yml,例如application.yml

基本语法

  • YAML 使用 Unicode 字符,也可使用 UTF-8 或 UTF-16。
  • 数据结构采用键值对的形式,即键名称: 值,注意冒号后面要有空格。
  • 数组中的每个元素单独一行,并以- 开头,例如- 陈皮。或使用方括号,元素用逗号隔开,例如["陈皮", "狗蛋"]。注意短横杆和逗号后面都有空格。
  • 散列表中的每个成员单独一行,使用键值对形式,例如name: 陈皮。或者使用大括号并用逗号分开,例如"name": 陈皮, "age": 18
  • 字符串值一般不使用引号,必要时可使用,使用双引号表示字符串时,会转义字符串中的特殊字符(例如\\n)。使用单引号时不会转义字符串中的特殊字符。
  • 字母大小写敏感。
  • 使用缩进表示层级关系,缩进使用空格不推荐使用 tab,因为在不同系统 tab 长度可能不一样。
  • 缩进的空格数可以任意,只要相同层级的元素左对齐即可。
  • 用连续三个连字号---划分多个文档块。还有选择性的连续三个点号...表示文件结尾。
  • #表示注释,可以出现在一行中的任何位置,单行注释。
  • 使用逗号和冒号时,后面都必须接一个空白字符。所以可以在字符串或数值中自由加入分隔符号(例如5,280或者http://www.wikipedia.org)而不需要使用引号。

数据类型

  • 标量:单个的、不可再分的值。
  • 对象:键值对的集合。
  • 数组:一组按次序排列的值,又称为序列或者列表。

标量

标量是最基础的数据类型,不可再分的值,他们一般用于表示单个的变量,有以下七种:

  1. 字符串
  2. 布尔值
  3. 整数
  4. 浮点数
  5. Null
  6. 时间
  7. 日期
# 字符串
string.value: 陈皮

# 布尔值,true或false
boolean.value: true
boolean.value1: false

# 整数
int.value: 10
int.value1: 0b1010_0111_0100_1010_1110 # 二进制

# 浮点数
float.value: 3.14159
float.value1: 314159e-5 # 科学计数法

# Null,~代表null
null.value: ~

# 时间,时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
datetime.value: !!timestamp 2021-04-13T10:31:00+08:00

# 日期,日期必须使用ISO 8601格式,即yyyy-MM-dd
date.value: !!timestamp 2021-04-13

在程序中引入以上配置变量,如下所示。

package com.chenpi.config;

import java.util.Date;
import lombok.Getter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/4/10
 */
@Component
@Getter
@ToString
public class PropConfig 

  @Value("$string.value")
  private String stringValue;

  @Value("$boolean.value")
  private boolean booleanValue;

  @Value("$boolean.value1")
  private boolean booleanValue1;

  @Value("$int.value")
  private int intValue;

  @Value("$int.value1")
  private int intValue1;

  @Value("$float.value")
  private float floatValue;

  @Value("$float.value1")
  private float floatValue1;

  @Value("$null.value")
  private String nullValue;

  @Value("$datetime.value")
  private Date datetimeValue;

  @Value("$date.value")
  private Date dateValue;


对以上对象输出打印,结果如下:

PropConfig(stringValue=陈皮, booleanValue=true, booleanValue1=false, intValue=10, intValue1=685230, floatValue=3.14159, floatValue1=3.14159, nullValue=, datetimeValue=Wed Apr 14 00:31:00 CST 2021, dateValue=Tue Apr 13 22:00:00 CST 2021)

对象

单个变量使用键值对 key: value,使用缩进层级的键值对表示一个对象的属性,如下所示:

person:
  name: 陈皮
  age: 18
  man: true

也可以使用大括号的形式key: key1: value1, key2: value2, ...,如下所示:

person: name: 陈皮, age: 18, man: true

然后在程序对这几个属性注入到 Person 对象中,注意 Person 类注入的属性要添加 get 和 set 方法,不然属性无法获取到配置文件的值。使用@ConfigurationProperties代替@value,可以很好的解析复杂对象。

package com.chenpi;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/4/10
 */
@Configuration
@ConfigurationProperties(prefix = "person")
@Getter
@Setter
@ToString
public class Person 

  private String name;
  private int age;
  private boolean man;


// Person(name=陈皮, age=18, man=true)

数组

使用短横杆加空格开头的行,组成数组的每一个元素,如下的 address 字段:

person:
  name: 陈皮
  age: 18
  man: true
  address:
    - 深圳
    - 北京
    - 广州

也可以使用中括号进行行内显示形式,如下:

person:
  name: 陈皮
  age: 18
  man: true
  address: [深圳, 北京, 广州]

在程序中引入以上配置变量,如下所示。

package com.chenpi;

import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/4/10
 */
@Configuration
@ConfigurationProperties(prefix = "person")
@Getter
@Setter
@ToString
public class Person 

  private String name;
  private int age;
  private boolean man;
  private List<String> address;


// Person(name=陈皮, age=18, man=true, address=[深圳, 北京, 广州])

如果数组字段的成员也是一个数组,继续使用嵌套的形式,如下所示:

person:
  name: 陈皮
  age: 18
  man: true
  address: [深圳, 北京, 广州]
  twoArr:
    -
      - 2
      - 3
      - 1
    -
      - 10
      - 12
      - 30
package com.chenpi;

import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/4/10
 */
@Configuration
@ConfigurationProperties(prefix = "person")
@Getter
@Setter
@ToString
public class Person 

  private String name;
  private int age;
  private boolean man;
  private List<String> address;
  private List<List<Integer>> twoArr;


// Person(name=陈皮, age=18, man=true, address=[深圳, 北京, 广州], twoArr=[[2, 3, 1], [10, 12, 30]])

如果数组成员是一个对象,则可以用如下两种形式:

childs:
  -
    name: 小红
    age: 10
  -
    name: 小王
    age: 15
childs: [name: 小红, age: 10, name: 小王, age: 15]

文本块

如果你想引入多行的文本块,可以使用|符号,注意在冒号:|符号之间要有空格。

person:
  name: |
    Hello Java!!
    I am fine!
    Thanks! GoodBye!

它和加双引号的效果一样,双引号能转义特殊字符:

person:
  name: "Hello Java!!\\nI am fine!\\nThanks! GoodBye!"

显示指定类型

有时我们需要显示指定某些值的类型,可以使用!(感叹号)显式指定类型。!单叹号通常是自定义类型,!!双叹号是内置类型,例如:

# !!str指定为字符串
string.value: !!str HelloWorld!
# !!timestamp指定为日期时间类型
datetime.value: !!timestamp 2021-04-13T02:31:00+08:00

内置的类型如下:

  • !!int:整数类型
  • !!float:浮点类型
  • !!bool:布尔类型
  • !!str:字符串类型
  • !!binary:二进制类型
  • !!timestamp:日期时间类型
  • !!null:空值
  • !!set:集合类型
  • !!omap,!!pairs:键值列表或对象列表
  • !!seq:序列
  • !!map:散列表类型

引用

引用会用到&锚点和*星号,&用来建立锚点,<<表示合并到当前数据,*用来引用锚点。

xiaohong: &xiaohong
  name: 小红
  age: 20

dept:
  id: D15D8E4F6D68A4E88E
  <<: *xiaohong

上面最终相当于如下:

xiaohong:
  name: 小红
  age: 20

dept:
  id: D15D8E4F6D68A4E88E
  name: 小红
  age: 20

还有一种文件内引用,引用已经定义好的变量,如下:

base.host: https://chenpi.com
add.person.url: $base.host/person/add  # 最终值为 https://chenpi.com/person/add

单文件多配置

可以在同一个文件中,实现多文档分区,即多配置。例如在 Spring 项目 application.yml 文件中,通过---分隔多个不同配置集,根据spring.profiles.active的值来决定启用哪个配置集。

# 公共配置
spring:
  profiles:
    active: pro # 指定使用哪个文档块
---
# 开发环境配置
spring:
  profiles: dev # profiles属性代表配置的名称

server:
  port: 8080
---
# 生产环境配置
spring:
  profiles: pro

server:
  port: 8081

本次分享到此结束啦~~

如果觉得文章对你有帮助,点赞、收藏、关注、评论,您的支持就是我创作最大的动力!

以上是关于YAML 详解与实战的主要内容,如果未能解决你的问题,请参考以下文章

yaml-cpp 总是创建一个大小为 0 的标量节点

Python的PyYAML模块详解

ansible-playbook使用详解

YAML块标量头

原创ansible-playbook 详解

SnowFlake 雪花算法详解与实现