ITPub博客

首页 > 应用开发 > Javascript > Y服务-你真的懂 Yaml 吗?

Y服务-你真的懂 Yaml 吗?

原创 Javascript 作者:kbfrmcob 时间:2020-08-12 10:17:34 0 删除 编辑

  一、什么是 Yaml

  来自百科的定义:

  "Yaml 是一个可读性高,易用的数据序列化格式,由 Clark Evans 在2001年首次发表。"

  可见 Yaml 并不是一个很新的东西,只是在以前接触的人不多罢了。此外,Yaml也被各种编程语言及框架所支持, 通用性很高。

  在Java体系中,一般的微服务框架都支持甚至优先推荐使用 Yaml 作为首选的配置语言。

  而 Yaml 本身具有什么特点? 看看下面的一个实例:

  environments:

  dev:

  url: https://dev.example.com

  name: Developer Setup

  prod:

  url: https://another.example.com

  name: My Cool App

  这段语法等价的 Properties 为:

  environments.dev.url=https://dev.example.com

  environments.dev.name=Developer Setup

  environments.prod.url=https://another.example.com

  environments.prod.name=My Cool App

  可见, yaml 相对来说更加的结构化,更适合用来表达一个对象。

  它在语法上有这样的特点:

  大小写敏感

  使用空格缩进表示层级关系,摒弃使用Tab键,这主要是考虑到不同平台上文本展现时需要对齐

  缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

  使用 # 开头作为注释行

  使用 连接符(-)开头来描述数组元素

  对比 Properties

  Properties 可以很好的实现 Key-Value 的配置,包括作为一些国际化内容的配置方式。

  但 Properties 很难表现多层级的嵌套关系,此时如果用 Yaml 可以较好的弥补该短板。

  对比 Json

  Yaml 与 Json本身没有太多的优劣之分,两者都是结构化的表达式语言,但是Json的设计重点在于简单易用、方便传输的特性;

  而 Yaml 则侧重于可读性(更加在乎外观),几乎可以把 Yaml 看做是 Json 的一个"超集",即可读性更高(更漂亮) 的结构化格式。

  此外,Json更加便于生成和解析,适合在各种跨语言、分布式的环境中传输和交互;与此同时, Yaml 则一般只是用作的配置较多。

  关于 Yaml 的定义可以访问下面的地址:

  http://www.yaml.org/spec/1.2/spec.html

  二、Yaml 的语法

  Yaml 是非常简单的, 它所定义的元素只有三个:

  对象:就是键值对的集合,对应于Java 中的 HashMap

  数组:指一组按序排列的值,对应于Java 中的 List

  单值:单个的、不可再分的值,比如 3,"Jackson"

  对象如何表示

  一个对象的属性、嵌套关系通过空格缩进对齐来表示,如下:

  article:

  title: 一个人的自白书

  author:

  name: 陈玲

  gender: female

  数组如何表示

  数组的元素通过连接符(-)来表示,如下:

  article:

  title: 一个人的自白书

  tags:

  - 传记

  - 社会

  - 人物

  构成对象、数组内容的基本单元是单值,Yaml支持的单个值的类型有七种,如下:

  类型 范例

  字符串 Bob

  布尔值 true

  整数 199

  浮点数 19.91

  Null ~

  时间 2001-12-14T22:14:09.10+08:00

  日期 2019-01-09

  其中,日期、时间使用的是 ISO 8601 国际标准格式,关于它的定义可以参考:

  https://www.w3.org/TR/NOTE-datetime

  一般情况下单个值会在一行内结束。但如果遇到多行的字符串,可以使用一些特殊字符表示,

  比如:

  text: |

  Hello

  World

  对应的结果为:

  { text: 'Hello\nWorld\n' }

  可以用+表示保留字符串末尾的换行,-表示删除字符串末尾的换行:

  text1: |+

  Hello

  text2: |-

  Hello

  对应的结果为:

  { text1: 'Hello\n\n\n', text2: 'Hello' }

  除此之外,Yaml 还可以支持引用、函数、正则表达式等高级用法,但项目上一般很少用到。

  三、操作 Yaml

  Y服务-你真的懂 Yaml 吗?

  目前用来操作 Yaml 的常用组件是 Snake Yaml,这个库支持标准的 Yaml 1.1 版本。

  SpringBoot 官方文档也介绍了整合该框架的方式,参考下面的地址:

  https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-loading-yaml

  下面提供 将SnakeYaml 整合到项目的样例。

  A. 引入框架

  在Maven的pom.xml文件中添加:

  <dependency>

  <groupId>org.yaml</groupId>

  <artifactId>snakeyaml</artifactId>

  <version>1.21</version>

  </dependency>

  B. 代码片段

  实现加载配置文件

  如下面的代码,实现了从类路径config.yml文件中加载 yaml 配置内容:

  InputStream inputStream = YamlUtil.class.getClassLoader()

  .getResourceAsStream("config.yml");

  Yaml yaml = new Yaml();

  Map<String, Object> objectMap = yaml.load(inputStream);

  System.out.println(objectMap.get("path"));

  实现对象转换

  定义如下的Pojo 对象:

  public static class A{

  private String name = "hello";

  private List<B> bs = new ArrayList<B>();

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name = name;

  }

  public List<B> getBs() {

  return bs;

  }

  public void setBs(List<B> bs) {

  this.bs = bs;

  }

  }

  public static class B{

  private String id = UUID.randomUUID().toString();

  public String getId() {

  return id;

  }

  public void setId(String id) {

  this.id = id;

  }

  }

  通过 SnakeYaml 将对象输出为 Yaml 格式的代码:

  A a = new A();

  a.getBs().add(new B());

  a.getBs().add(new B());

  Yaml yaml = new Yaml();

  String aString = yaml.dumpAsMap(a);

  System.out.println(aString);

  输出结果如下:

  bs:

  - id: b3688f05-ea7e-436b-bc9a-9c5df555c7fd

  - id: 7906224d-8ecc-43b8-bc3b-07985bc18ebd

  name: hello

  此时如果希望将Yaml 文本反过来转换为 A 对象,可以执行下面的代码:

  A a1 = new Yaml().parseToObject(aString, A.class);

  ...

  C. 完整案例

  最终,我们可以将 Yaml 文档的操作封装为一个工具类,方便在业务代码中集成。

  YamlUtil.java

  public class YamlUtil {

  /**

  * 从资源文件加载内容,并解析为Map对象

  *

  * @param path

  * @return

  */

  public static Map<String, Object> loadToMap(String path) {

  if (StringUtils.isEmpty(path)) {

  return Collections.emptyMap();

  }

  InputStream inputStream = YamlUtil.class.getClassLoader()

  .getResourceAsStream(path);

  Yaml yaml = new Yaml();

  Map<String, Object> objectMap = yaml.load(inputStream);

  return objectMap;

  }

  /**

  * 将字符串解析为Map对象

  *

  * @param content

  * @return

  */

  public static Map<String, Object> parseToMap(String content) {

  if (StringUtils.isEmpty(content)) {

  return Collections.emptyMap();

  }

  Yaml yaml = new Yaml();

  Map<String, Object> objectMap = yaml.load(content);

  return objectMap;

  }

  /**

  * 将字符串解析为类对象

  *

  * @param content

  * @param clazz

  * @param <T>

  * @return

  */

  public static <T> T parseToObject(String content, Class<T> clazz) {

  if (StringUtils.isEmpty(content) || clazz == null) {

  return null;

  }

  Yaml yaml = new Yaml(new Constructor(clazz));

  T object = yaml.load(content);

  return object;

  }

  /**

  * 格式化对象

  *

  * @param object

  * @return

  */

  public static String format(Object object) {

  Yaml yaml = new Yaml();

  return yaml.dumpAsMap(object);

  }

  }

  至此,我们已经完成了 Yaml 的读写。当然,除了上述的Snake Yaml 之外,还可以使用 流行的 Jackson 组件了进行解析,这里不再过多赘述,有兴趣的朋友可以自行尝试。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69976870/viewspace-2711024/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2020-07-14

  • 博文量
    12
  • 访问量
    17962