Java YAML 序列化



YAML 簡介

什么是 YAML ?

  • YAML(YAML Ain't Markup Language,即 YAML 不是一種標記語言),也可以叫做 YML 。YAML 是一種直觀的、能夠被電腦識別的數據序列化格式,容易被人類閱讀,容易和腳本語言交互,可以被支持 YAML 庫的不同編程語言程序所導入(如 C/C++、Ruby、Python、Java、Perl、C#、PHP 等)。

  • YML 文件是以數據為核心的,相比 JSON、XML 等方式更加簡潔。

  • YAML 文件的擴展名可以使用 .yml 或者 .yaml 。

  • YAML 官網

image

YAML 語法

  • 大小寫敏感。
  • 數據值前邊必須要有空格(大於等於 1 個)作為分隔符。
  • 使用縮進表示層級關系。
  • 縮進時不允許使用 Tab 鍵,只允許使用空格(各個系統 Tab對應的 空格數目可能不同,導致層次混亂)。
  • 縮進的空格數目不重要,只要相同層級的元素左側對齊即可。
  • # 表示注釋,從這個字符一直到行尾,都會被解析器忽略。

YAML 數據格式

  • 對象(map):鍵值對的集合
# 行內寫法
address: {province: 山東, city: 濟南}

# 多行寫法
address:
  province: 山東
  city: 濟南
  • 數組:一組按次序排列的值
# 行內寫法
hobbyList: [游泳, 跑步]

# 多行寫法
hobbyList:
  - 游泳
  - 跑步
  • 純量:單個的、不可再分的值
# 字符串默認不用加引號,但包含空格或特殊字符必須加引號,單引號或雙引號都可以
# 單引號:不識別轉移字符,即原樣輸出
# 雙引號:識別轉移字符,如 \r、\n 等
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
  • 參數引用
name: lisi

person:
  name: ${name}  # 引用上邊定義的name值

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 依賴:
<!-- Bean類的GETTER、SETTER注解 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>
  • 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<String> hobbyList;
}
  • Address 實體類:
import lombok.*;

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

    private String province;
    private String city;
}

snakeyaml 庫

Maven 依賴

<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.21</version>
</dependency>

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<String, Object> 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 依賴:

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-yaml</artifactId>
  <version>2.12.0</version>
</dependency>

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:
- "游泳"
- "跑步"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM