1.概述

本文,我们将学习如何使用SnakeYAML库将

YAML文档转换为Java对象,以及JAVA对象如何序列化为YAML文档

2.项目设置

要在项目中使用SnakeYAML,需要添加Maven依赖项(可在此处找到最新版本):

<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.25</version>
</dependency>

3.入口点

YAML类是API的入口点:

Yaml yaml = new Yaml()

由于实现不是线程安全的,因此不同的线程必须具有自己的Yaml实例。

4.加载YAML文档

SnakeYAML支持从StringInputStream加载文档,我们从定义一个简单的YAML文档开始,然后将文件命名为customer.yaml

firstName: "John"
lastName: "Doe"
age: 20

4.1。基本用法

现在,我们将使用Yaml类来解析上述YAML文档:

Yaml yaml = new Yaml();
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("customer.yaml");
Map<String, Object> obj = yaml.load(inputStream);
System.out.println(obj);

上面的代码生成以下输出:

{firstName=John, lastName=Doe, age=20}

默认情况下,load()方法返回一个Map对象。查询Map对象时,我们需要事先知道属性键的名称,否则容易出错。更好的办法是自定义类型。

4.2自定义类型解析

SnakeYAML提供了一种将文档解析为自定义类型的方法

让我们定义一个Customer类,然后尝试再次加载该文档:

public class Customer {

    private String firstName;
private String lastName;
private int age; // getters and setters
}

现在我么来加载:

Yaml yaml = new Yaml();
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("customer.yaml");
Customer customer = yaml.load(inputStream);

还有一种方法是使用Constructor:

Yaml yaml = new Yaml(new Constructor(Customer.class));

4.3。隐式类型

如果没有为给定属性定义类型,则库会自动将值转换为隐式type

例如:

1.0 -> Float
42 -> Integer
2009-03-30 -> Date

让我们使用一个TestCase来测试这种隐式类型转换:

@Test
public void whenLoadYAML_thenLoadCorrectImplicitTypes() {
Yaml yaml = new Yaml();
Map<Object, Object> document = yaml.load("3.0: 2018-07-22"); assertNotNull(document);
assertEquals(1, document.size());
assertTrue(document.containsKey(3.0d));
}

4.4 嵌套对象

SnakeYAML 支持嵌套的复杂类型。

让我们向“ customer.yaml”添加“ 联系方式”  和“ 地址” 详细信息并将新文件另存为customer_with_contact_details_and_address.yaml.

现在,我们将分析新的YAML文档:

firstName: "John"
lastName: "Doe"
age: 31
contactDetails:
- type: "mobile"
number: 123456789
- type: "landline"
number: 456786868
homeAddress:
line: "Xyz, DEF Street"
city: "City Y"
state: "State Y"
zip: 345657

我们来更新java类:

public class Customer {
private String firstName;
private String lastName;
private int age;
private List<Contact> contactDetails;
private Address homeAddress;
// getters and setters
} public class Contact {
private String type;
private int number;
// getters and setters
} public class Address {
private String line;
private String city;
private String state;
private Integer zip;
// getters and setters
}

现在,我们来测试下Yamlload()

@Test
public void
whenLoadYAMLDocumentWithTopLevelClass_thenLoadCorrectJavaObjectWithNestedObjects() { Yaml yaml = new Yaml(new Constructor(Customer.class));
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("yaml/customer_with_contact_details_and_address.yaml");
Customer customer = yaml.load(inputStream); assertNotNull(customer);
assertEquals("John", customer.getFirstName());
assertEquals("Doe", customer.getLastName());
assertEquals(31, customer.getAge());
assertNotNull(customer.getContactDetails());
assertEquals(2, customer.getContactDetails().size()); assertEquals("mobile", customer.getContactDetails()
.get(0)
.getType());
assertEquals(123456789, customer.getContactDetails()
.get(0)
.getNumber());
assertEquals("landline", customer.getContactDetails()
.get(1)
.getType());
assertEquals(456786868, customer.getContactDetails()
.get(1)
.getNumber());
assertNotNull(customer.getHomeAddress());
assertEquals("Xyz, DEF Street", customer.getHomeAddress()
.getLine());
}

4.5。类型安全的集合

当给定Java类的一个或多个属性是泛型集合类时,需要通过TypeDescription来指定泛型类型,以以便可以正确解析。

让我们假设一个 一个Customer拥有多个Contact

firstName: "John"
lastName: "Doe"
age: 31
contactDetails:
- { type: "mobile", number: 123456789}
- { type: "landline", number: 123456789}

为了能正确解析,我们可以在顶级类上为给定属性指定TypeDescription 

Constructor constructor = new Constructor(Customer.class);
TypeDescription customTypeDescription = new TypeDescription(Customer.class);
customTypeDescription.addPropertyParameters("contactDetails", Contact.class);
constructor.addTypeDescription(customTypeDescription);
Yaml yaml = new Yaml(constructor);

4.6。载入多个文件

在某些情况下,单个文件中可能有多个YAML文档,而我们想解析所有文档。所述YAML类提供了一个LOADALL()方法来完成这种类型的解析。

假设下面的内容在一个文件中:

---
firstName: "John"
lastName: "Doe"
age: 20
---
firstName: "Jack"
lastName: "Jones"
age: 25

我们可以使用loadAll()方法解析以上内容,如以下代码示例所示:

@Test
public void whenLoadMultipleYAMLDocuments_thenLoadCorrectJavaObjects() {
Yaml yaml = new Yaml(new Constructor(Customer.class));
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("yaml/customers.yaml"); int count = 0;
for (Object object : yaml.loadAll(inputStream)) {
count++;
assertTrue(object instanceof Customer);
}
assertEquals(2,count);
}

5.生成YAML文件

SnakeYAML 支持 将java对象序列化为yml。

5.1。基本用法

我们将从一个将Map <String,Object>的实例转储到YAML文档(String)的简单示例开始:

@Test
public void whenDumpMap_thenGenerateCorrectYAML() {
Map<String, Object> data = new LinkedHashMap<String, Object>();
data.put("name", "Silenthand Olleander");
data.put("race", "Human");
data.put("traits", new String[] { "ONE_HAND", "ONE_EYE" });
Yaml yaml = new Yaml();
StringWriter writer = new StringWriter();
yaml.dump(data, writer);
String expectedYaml = "name: Silenthand Olleander\nrace: Human\ntraits: [ONE_HAND, ONE_EYE]\n"; assertEquals(expectedYaml, writer.toString());
}

上面的代码产生以下输出(请注意,使用LinkedHashMap的实例将保留输出数据的顺序):

name: Silenthand Olleander
race: Human
traits: [ONE_HAND, ONE_EYE]

5.2。自定义Java对象

我们还可以选择将自定义Java类型转储到输出流中

@Test
public void whenDumpACustomType_thenGenerateCorrectYAML() {
Customer customer = new Customer();
customer.setAge(45);
customer.setFirstName("Greg");
customer.setLastName("McDowell");
Yaml yaml = new Yaml();
StringWriter writer = new StringWriter();
yaml.dump(customer, writer);
String expectedYaml = "!!com.baeldung.snakeyaml.Customer {age: 45, contactDetails: null, firstName: Greg,\n homeAddress: null, lastName: McDowell}\n"; assertEquals(expectedYaml, writer.toString());
}

生成内容会包含!!com.baeldung.snakeyaml.Customer,为了避免在输出文件中使用标签名,我们可以使用库提供的  dumpAs()方法。

因此,在上面的代码中,我们可以进行以下调整以删除标记:

yaml.dumpAs(customer, Tag.MAP, null);

六 结语

本文说明了SnakeYAML库解析和序列化YAML文档。

所有示例都可以在GitHub项目中找到。

附录


作者:Jadepeng

出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi

您的支持是对博主最大的鼓励,感谢您的认真阅读。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

JAVA使用SnakeYAML解析与序列化YAML的更多相关文章

  1. Java使用snakeyaml解析yaml

    YAML Yaml是一种"是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言."类似于XML但比XML更简洁,语法详见 http://www.ruan ...

  2. Java下利用Jackson进行JSON解析和序列化

    Java下利用Jackson进行JSON解析和序列化   Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行 ...

  3. 【转载】Java下利用Jackson进行JSON解析和序列化

    参考资料: https://blog.csdn.net/sdut406/article/details/85647982 Java下常见的Json类库有Gson.JSON-lib和Jackson等,J ...

  4. Java下利用Jackson进行JSON解析和序列化1

    Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行JSON和Java对象转换,下面给出一些Jackson的J ...

  5. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  6. Java 面试知识点解析(六)——数据库篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  7. Java的XML解析

    XML:(eXtensible Markup Language) 可扩展标记语言 是一种数据格式,用于存储和传输数据 声明一个xml文件 <?xml version="1.0" ...

  8. android菜鸟学习笔记19----Android数据存储(三)XML文件的解析及序列化

    Android内置了PULL解析器的XPP3实现,以及SAX解析器等,可以直接使用PULL或SAX解析XML,直接把JAVA中进行PULL或SAX解析的代码直接拿来用,遗忘的话,可以参考java拾遗1 ...

  9. java拾遗3----XML解析(三) StAX PULL解析

    使用PULL方式解析XML: Pull是STAX的一个实现 StAX是The Streaming API for XML的缩写,一种利用拉模式解析(pull-parsing)XML文档的API StA ...

随机推荐

  1. 【dp】Arrange the Schedule

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3538 题意:如题. 题解: 假如 一组数据 ...(n1)A.. ...

  2. Spring Boot: Spring Doc生成OpenAPI3.0文档

    1. 概述 公司正好最近在整理项目的文档,且文档对于构建REST API来说是至关重要的.在这篇文章中,我将介绍Spring Doc , 一个基于OpenAPI 3规范简化了Spring Boot 1 ...

  3. DNS name

    DNS name 指的反向解析的域名.

  4. Linux配置SSH和Xshell连接服务器

    >>>>>Ubuntu安装和配置ssh教程 SSH分为客户端 openssh-client 和服务器 openssh-server,可以利用以下命令确认电脑 上是否安装了 ...

  5. 性能测试——记weblogic 连接池满无法链接故障诊断过程

    记weblogic 连接池满无法链接故障诊断过程 前段时间公司负责建行的一个票据系统在,上线前几个分行试运行环境下,每天后台日志都会报oracle.jdbc.xa.OracleXAException, ...

  6. nmap中的详细命令

    nmap全部参数详解-A 综合性扫描端口:80http 443https 53dns 25smtp 22ssh 23telnet20.21ftp 110pop3 119nntp 143imap 179 ...

  7. Single-Shot Object Detection with Enriched Semantics

    整合一下能够查到的资料,然后结合自己的理解,算是对这篇文章的一个小小的总结吧.这是CVPR2018的一篇关于小目标检测的文章,出发点是作者认为小目标的检测信息随着层数的增加而不断地丢失了,所以想利用语 ...

  8. Maven安装目录分析

    maven目录结构介绍 bin: 包含了mvn运行的脚本(既在cmd输入命令执行依赖,在命令行输入任何一条mvn命令时,实际上就是在调用这些脚本) boot: 该目录只包含一个文件,是一个类加载器,m ...

  9. 实战webpack系列03

    03.Webpack的强大功能 一.生成Source Maps(使调试更容易) 通过简单的配置,webpack就可以在打包时为我们生成的source maps,这为我们提供了一种对应编译文件和源文件的 ...

  10. js人民币转大写

    <input type="text" oninput="OnInput (event)" value="1234567"> &l ...