Java YAML 序列化


目录
  • YAML 简介
    • 什么是 YAML ?
    • YAML 数据格式
  • YAML 序列化
    • yaml 文件与 Bean 类
    • snakeyaml 库
      • 1)yaml、map 互转
      • 2)yaml 转 Bean
      • 3)Bean 转 yaml
    • jackson 库
      • 1)yaml 转 Bean
      • 2)Bean 转 yaml


YAML 简介

什么是 YAML ?

YAML(YAML Ain't Markup Language,YAML不是一种标记语言),也可以叫做 YML,是一种人性化的数据序列化的语言,类似于XML、JSON。SpringBoot 的配置文件就支持 yaml 文件。

  • YAML 相比 JSON 的优势:更加已读、可写注释。
  • YAML 文件既可以 .yaml 结尾,也可以 .yml 结尾,支持这两种方式的扩展名。
  • YAML 官网

YAML 语法

  • 大小写敏感。
  • 使用缩进表示层级关系。
  • 缩进时不允许使用 Tab 键,只允许使用空格。
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可。
  • 使用 # 表示注释,从这个字符一直到行尾,都会被解析器忽略。

YAML 数据格式

对象

# 写在一行
address: {province: 山东, city: 济南}

# 写在多行
address:
  province: 山东
  city: 济南

数组

# 写在一行
hobbyList: [游泳, 跑步]

# 写在多行
hobbyList:
  - 游泳
  - 跑步

纯量

# 字符串默认不用加引号,包含空格或特殊字符必须加引号,单引号或双引号都可以。
userId: S123
username: "lisi"
password: '123456'
province: 山东
city: "济南 : ss"

# 布尔值
success: true

# 整数
age: 13

# 浮点数
weight: 75.5

# Null
gender: ~

# 时间:使用 ISO8601 标准
createDate: 2001-12-14T21:59:43.10+05

YAML 序列化

yaml 文件与 Bean 类

示例:yaml 文件

userId: 1
username: lisi
password: 123456
address: {province: 山东, city: 济南}
hobbyList: [游泳, 跑步]

或:

userId: 1
username: "lisi"
password: '123456'
address:
  province: 山东
  city: "济南 : ss"
hobbyList:
  - 游泳
  - 跑步

示例:Bean 实体类

  • Maven 依赖:


    org.projectlombok
    lombok
    RELEASE
    compile

  • User 实体类:
import lombok.*;

import java.security.Timestamp;
import java.util.List;

@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String userId;
    private String username;
    private String password;
    private Timestamp createDate;
    private Address address;
    private List hobbyList;
}
  • Address 实体类:
import lombok.*;

@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Address {

    private String province;
    private String city;
}

snakeyaml 库

Maven 依赖



    org.yaml
    snakeyaml
    1.21

1)yaml、map 互转

使用 yaml 对象中的 load 方法会返回一个 map 对象,然后遍历这个 map 即可得到自己想要的数据。

import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.util.Map;

public class YamlDemo {

    public static void main(String[] args) {
        // yaml 读取
        InputStream in = YamlDemo.class.getClassLoader().getResourceAsStream("test.yaml");
        Yaml yaml = new Yaml();
        Map map = yaml.loadAs(in, Map.class);
        map.forEach(
                (String key, Object value) -> {
                    System.out.println("key: "+key+" value: "+value);
                }
        );
        /* 执行结果:
            key: userId value: 1
            key: username value: lisi
            key: password value: 123456
            key: address value: {province=山东, city=济南}
            key: hobbyList value: [游泳, 跑步]
         */

        // yaml 写入
        map.put("username", "zhangsan");  // 修改读取的yaml内容
        try {
            // 将修改后的内容写入new_user.yaml
            yaml.dump(map, new OutputStreamWriter(new FileOutputStream(new File("new_user.yaml"))));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

key: userId value: 1
key: username value: lisi
key: password value: 123456
key: address value: {province=山东, city=济南}
key: hobbyList value: [游泳, 跑步]

2)yaml 转 Bean

import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.Objects;

public class YamlDemo {

    public static void main(String[] args) {
        InputStream resource = YamlDemo.class.getClassLoader().getResourceAsStream("test.yaml");
        if (Objects.nonNull(resource)) {
            Yaml yaml = new Yaml();
            User user = yaml.loadAs(resource, User.class);
            System.out.println(user.getClass());  // class User
            System.out.println(user);  // User(userId=1, username=lisi, password=123456, createDate=null, address=Address(province=山东, city=济南), hobbyList=[游泳, 跑步])
        }
    }
}

3)Bean 转 yaml

import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.Arrays;

public class YamlDemo {

    public static void main(String[] args) {
        User user = new User();
        user.setUserId("1");
        user.setUsername("lisi");
        user.setPassword("123456");
        user.setAddress(new Address("山东", "济南"));
        user.setHobbyList(Arrays.asList("游泳", "跑步"));
        Yaml yaml = new Yaml();
        String userString = yaml.dump(user);  // 输出字符串
        try {
            yaml.dump(user, new FileWriter("Bean.yaml"));  // 输出文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(userString);
        System.out.println(yaml.loadAs(userString, User.class));
    }
}

输出结果:

!!User  # 首行为:!!+全类名
address: {city: 济南, province: 山东}
createDate: null
hobbyList: [游泳, 跑步]
password: '123456'
userId: '1'
username: lisi

上面的对象和数组是显示在一行的,我们也可以通过自定义序列化显示为多行。

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.Arrays;

public class YamlDemo {

    public static void main(String[] args) {
        User user = new User();
        user.setUserId("1");
        user.setUsername("lisi");
        user.setPassword("123456");
        user.setAddress(new Address("山东", "济南"));
        user.setHobbyList(Arrays.asList("游泳", "跑步"));
        DumperOptions dumperOptions = new DumperOptions();
        dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        Yaml yaml = new Yaml(dumperOptions);
        String userString = yaml.dump(user);  // 输出字符串
        try {
            yaml.dump(user, new FileWriter("Bean.yaml"));  // 输出文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(userString);
        System.out.println(yaml.loadAs(userString, User.class));
    }
}

执行结果:

!!User
address:
  city: 济南
  province: 山东
createDate: null
hobbyList:
- 游泳
- 跑步
password: '123456'
userId: '1'
username: lisi

jackson 库

jackson-dataformat-yaml 是在 snakeyaml 的基础上又封装了一层。

Maven 依赖:


  com.fasterxml.jackson.dataformat
  jackson-dataformat-yaml
  2.12.0

1)yaml 转 Bean

import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

public class YamlDemo {

    public static void main(String[] args) {
        InputStream resource = YamlDemo.class.getClassLoader().getResourceAsStream("test.yaml");
        if (Objects.nonNull(resource)) {
            YAMLMapper yamlMapper = new YAMLMapper();
            User user = null;
            try {
                user = yamlMapper.readValue(resource, User.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(user.getClass());  // class User
            System.out.println(user);  // User(userId=1, username=lisi, password=123456, createDate=null, address=Address(province=山东, city=济南), hobbyList=[游泳, 跑步])
        }
    }
}

2)Bean 转 yaml

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;

import java.io.FileWriter;
import java.util.Arrays;

public class YamlDemo {

    public static void main(String[] args) {
        User user = new User();
        user.setUserId("1");
        user.setUsername("lisi");
        user.setPassword("123456");
        user.setAddress(new Address("山东", "济南"));
        user.setHobbyList(Arrays.asList("游泳", "跑步"));
        YAMLMapper yamlMapper = new YAMLMapper();
        try {
            System.out.println(yamlMapper.writeValueAsString(user));
            yamlMapper.writeValue(new FileWriter("Bean.yaml"), user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果:

---
userId: "1"
username: "lisi"
password: "123456"
createDate: null
address:
  province: "山东"
  city: "济南"
hobbyList:
- "游泳"
- "跑步"

相关