总结使用SnakeYAML解析与序列化YAML相关

SnakeYAML官网

https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-installation


一、pom.xml中添加依赖

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

二、Yaml基础知识

1 基本语法规则如下

大小写敏感;
使用缩进表示层级关系;
缩进时不允许使用Tab键,只允许使用空格;
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可;

 2 基本数据结构有三种

对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
一组连词线开头的行,构成一个数组;
纯量(scalars):单个的、不可再分的值

 3 复合结构

languages:
 - Ruby
 - Perl
 - Python 
websites:
 YAML: yaml.org 
 Ruby: ruby-lang.org 
 Python: python.org 
 Perl: use.perl.org 

4 锚点和引用

锚点&和别名*,可以用来引用;
&用来建立锚点(defaults),<<表示合并到当前数据,*用来引用锚点;

defaults: &defaults
  adapter:  postgres
  host:     localhost

development:
  database: myapp_development
  <<: *defaults

test:
  database: myapp_test
  <<: *defaults

就等价于:

defaults:
  adapter:  postgres
  host:     localhost

development:
  database: myapp_development
  adapter:  postgres
  host:     localhost

test:
  database: myapp_test
  adapter:  postgres
  host:     localhost

三、自定义类型解析

public class CarWithWheel {
    private String plate;
    private String year;
    private Wheel wheel;
    private List<Wheel> listWheels;
    private Map<Wheel, Date> mapWheels;
    private Object part;
    public String getPlate() {
        return plate;
    }
    public void setPlate(String plate) {
        this.plate = plate;
    }
    public String getYear() {
        return year;
    }
    public void setYear(String year) {
        this.year = year;
    }
    public Wheel getWheel() {
        return wheel;
    }
    public void setWheel(Wheel wheel) {
        this.wheel = wheel;
    }
    public List<Wheel> getListWheels() {
        return listWheels;
    }
    public void setListWheels(List<Wheel> listWheels) {
        this.listWheels = listWheels;
    }
    public Map<Wheel, Date> getMapWheels() {
        return mapWheels;
    }
    public void setMapWheels(Map<Wheel, Date> mapWheels) {
        this.mapWheels = mapWheels;
    }
    public Object getPart() {
        return part;
    }
    public void setPart(Object part) {
        this.part = part;
    }
}
public class Wheel {
    private int id;
    private String name;
    public Wheel() {
    }
    public Wheel(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 //Customer这个对象 载入多个文件的时候会用到

public class Customer {
    private String firstName;
    private String lastName;
    private int age;
    // getters and setters
}

四、生成YAML文件

1 准备pojo数据阶段:

CarWithWheel car1 = new CarWithWheel();
//plate
car1.setPlate("plate test");
//year
car1.setYear("2020");
//wheel
Wheel wheel = new Wheel();
wheel.setId(1);
wheel.setName("baoma");
car1.setWheel(wheel);
//listWheel
ArrayList<Wheel> listWheels = new ArrayList<>();
Wheel wheel2 = new Wheel(2,"benchi");
Wheel wheel3 = new Wheel(3,"dazhong");
Wheel wheel4 = new Wheel(4,"fengtian");
listWheels.add(wheel2);
listWheels.add(wheel3);
listWheels.add(wheel4);
car1.setListWheels(listWheels);
//mapWheels
Map<Wheel, Date> mapWheels = new HashMap<>();
Wheel wheel5 = new Wheel(5,"changcheng");
Wheel wheel6 = new Wheel(6,"jili");
Wheel wheel7 = new Wheel(7,"byd");
mapWheels.put(wheel5,new Date());
mapWheels.put(wheel6,new Date());
mapWheels.put(wheel7,new Date());
car1.setMapWheels(mapWheels);
//part
Wheel wheel8 = new Wheel(8,"part test");
car1.setPart(wheel8);

2 根据pojo生成yaml文件:

//real logic
 Constructor constructor = new Constructor(CarWithWheel.class);//root
TypeDescription carDescription = new TypeDescription(CarWithWheel.class);
carDescription.addPropertyParameters("listWheels", Wheel.class);
carDescription.addPropertyParameters("mapWheels", Wheel.class, Object.class);
constructor.addTypeDescription(carDescription);
//Representer
Representer representer = new Representer();
representer.addClassTag(CarWithWheel.class, Tag.MAP);
representer.addClassTag(Wheel.class, Tag.MAP);
//DumperOptions
// DumperOptions options = new DumperOptions();
// options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
// options.setCanonical(false); // display bean member attribute
// options.setExplicitStart(true); // display --- start
//入口
Yaml yaml = new Yaml(constructor,representer);
// Yaml yaml = new Yaml(constructor);
// Yaml yaml = new Yaml(constructor,representer);
yaml.dump(car1,new FileWriter(new File(car_with_wheel)));

3 最终生成的yaml文件如下图所示:

listWheels:
- {id: 2, name: benchi}
- {id: 3, name: dazhong}
- {id: 4, name: fengtian}
mapWheels:
  ? {id: 5, name: changcheng}
  : 2021-04-26T07:21:09.611Z
  ? {id: 6, name: jili}
  : 2021-04-26T07:21:09.611Z
  ? {id: 7, name: byd}
  : 2021-04-26T07:21:09.611Z
part: {id: 8, name: part test}
plate: plate test
wheel: {id: 1, name: baoma}
year: '2020'

五、文档解析

SnakeYAML支持从StringInputStream加载文档

1 加载单一的文件

情形一:Yaml.load() accepts a String

public void loadString() {
    Yaml yaml = new Yaml();
    String document = "hello: 25";
    Object load = yaml.load(document);
    System.out.println(load);
}

情形二:Yaml.load() accepts a InputStream

public void loadStream() {
     Yaml yaml = new Yaml();
     Object load = yaml.load(new FileInputStream(new File(yaml_path)));
     System.out.println(load);
}

载入多个文件

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

---
firstName: "John"
lastName: "Doe"
age: 20
---
firstName: "Jack"
lastName: "Jones"
age: 25
//Yaml.loadAll()
//If a String or a stream contains several documents, you may load them all with the Yaml.loadAll() method.
public void loadAll()  {
        Yaml yaml = new Yaml();
        Iterable<Object> objects = yaml.loadAll(new FileInputStream(new File(yaml_path_two)));
        Object load = objects;
        int counter = 0;
        for (Object data : objects) {
            System.out.println(data);
            counter++;
        }
        System.out.println(counter);
    }

3 简单的自定义类型解析

 自定义类型解析:自定义的简单的pojo --Customer 

 // Yaml yaml = new Yaml(new Constructor(Customer.class));
   Yaml yaml = new Yaml(new Constructor(Customer.class));
   Customer customer = yaml.load(new FileInputStream(new File(yaml_path)));
   System.out.println(customer);

4 嵌套对象

以刚才生成的car_with_wheel.yaml为例进行解析

listWheels:
- {id: 2, name: benchi}
- {id: 3, name: dazhong}
- {id: 4, name: fengtian}
mapWheels:
  ? {id: 5, name: changcheng}
  : 2021-04-26T07:21:09.611Z
  ? {id: 6, name: jili}
  : 2021-04-26T07:21:09.611Z
  ? {id: 7, name: byd}
  : 2021-04-26T07:21:09.611Z
part: {id: 8, name: part test}
plate: plate test
wheel: {id: 1, name: baoma}
year: '2020'

核心代码:

Constructor constructor = new Constructor(CarWithWheel.class);//root
Yaml yaml = new Yaml(constructor);
CarWithWheel carWithWheel =(CarWithWheel)yaml.load(new FileInputStream(new File(car_with_wheel)));
System.out.println(carWithWheel);

整个代码:


public void complexYaml(){
        //为了能正确解析,我们可以在顶级类上为给定属性指定TypeDescription
        Constructor constructor = new Constructor(CarWithWheel.class);//root
//        TypeDescription carDescription = new TypeDescription(CarWithWheel.class);
//        carDescription.addPropertyParameters("listWheels", Wheel.class);
//        carDescription.addPropertyParameters("mapWheels", Wheel.class, Object.class);
//        constructor.addTypeDescription(carDescription);
        //
        Yaml yaml = new Yaml(constructor);
        CarWithWheel carWithWheel =(CarWithWheel)yaml.load(new FileInputStream(new File(car_with_wheel)));
        System.out.println(carWithWheel);
//        carWithWheel.getListWheels().forEach(System.out::println);
//        for(Map.Entry entry:carWithWheel.getMapWheels().entrySet()){
//            System.out.println("key: " + entry.getKey()+","+"value: "+ entry.getValue());
//        }
//        System.out.println(carWithWheel.getPart());
//        System.out.println(carWithWheel.getPlate());
//        System.out.println(carWithWheel.getWheel());
//        System.out.println(carWithWheel.getYear());
    }

5 特殊的锚点处理

锚点&和别名*,可以用来引用;
&用来建立锚点(defaults),<<表示合并到当前数据,*用来引用锚点;

anchor.yaml内容如下图所示:

invoice: 34843
date   : 2001-01-23
billTo: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046
shipTo: *id001
product:
    - sku         : BL394D
      quantity    : 4
      description : Basketball
      price       : 450.00
    - sku         : BL4438H
      quantity    : 1
      description : Super Hoop
      price       : 2392.00
tax  : 251.42
total: 4443.52
comments:
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338.

加载yaml代码:

public void anchorYaml() throws FileNotFoundException {
   Yaml yaml = new Yaml();
   Object load = yaml.load(new FileInputStream(new File(anchor)));
   System.out.println(load);
}

最终的load的字符串:

{
    invoice = 34843,
    date = Tue Jan 23 08: 00: 00 CST 2001,
    billTo = {
        given = Chris,
        family = Dumars,
        address = {
            lines = 458 Walkman Dr.
                Suite # 292,
            city = Royal Oak,
            state = MI,
            postal = 48046
        }
    },
    shipTo = {
        given = Chris,
        family = Dumars,
        address = {
            lines = 458 Walkman Dr.
                Suite # 292,
            city = Royal Oak,
            state = MI,
            postal = 48046
        }
    },
    product = [{
            sku = BL394D,
            quantity = 4,
            description = Basketball,
            price = 450.0
        }, {
            sku = BL4438H,
            quantity = 1,
            description = Super Hoop,
            price = 2392.0
        }
    ],
    tax = 251.42,
    total = 4443.52,
    comments = Late afternoon is best.Backup contact is Nancy Billsmer @ 338 - 4338.
}

六、踩过的几个坑

1  生成的yaml文件中包含packName.className

!!com.example.rts_test.entity.CarWithWheel
listWheels:
- {id: 2, name: benchi}
- {id: 3, name: dazhong}
- {id: 4, name: fengtian}
mapWheels:
  ? {id: 7, name: byd}
  : 2021-04-26T09:00:19.727Z
  ? {id: 5, name: changcheng}
  : 2021-04-26T09:00:19.727Z
  ? {id: 6, name: jili}
  : 2021-04-26T09:00:19.727Z
part: !!com.example.rts_test.entity.Wheel {id: 8, name: part test}
plate: plate test
wheel: {id: 1, name: baoma}
year: '2020'

解决方法:增加Representer

before:

//real logic
Constructor constructor = new Constructor(CarWithWheel.class);//root
TypeDescription carDescription = new TypeDescription(CarWithWheel.class);
carDescription.addPropertyParameters("listWheels", Wheel.class);
carDescription.addPropertyParameters("mapWheels", Wheel.class, Object.class);
constructor.addTypeDescription(carDescription);
//入口
Yaml yaml = new Yaml(constructor);
yaml.dump(car1,new FileWriter(new File(car_with_wheel)));

after:

 //real logic
Constructor constructor = new Constructor(CarWithWheel.class);//root
TypeDescription carDescription = new TypeDescription(CarWithWheel.class);
carDescription.addPropertyParameters("listWheels", Wheel.class);
carDescription.addPropertyParameters("mapWheels", Wheel.class, Object.class);
constructor.addTypeDescription(carDescription);
//Representer
Representer representer = new Representer();
representer.addClassTag(CarWithWheel.class, Tag.MAP);
representer.addClassTag(Wheel.class, Tag.MAP);
Yaml yaml = new Yaml(constructor,representer);
yaml.dump(car1,new FileWriter(new File(car_with_wheel)));

最终结果:

listWheels:
- {id: 2, name: benchi}
- {id: 3, name: dazhong}
- {id: 4, name: fengtian}
mapWheels:
  ? {id: 5, name: changcheng}
  : 2021-04-26T09:03:11.229Z
  ? {id: 7, name: byd}
  : 2021-04-26T09:03:11.229Z
  ? {id: 6, name: jili}
  : 2021-04-26T09:03:11.229Z
part: {id: 8, name: part test}
plate: plate test
wheel: {id: 1, name: baoma}
year: '2020'

2 项目中有需要,load之后需要保留yaml中的锚点,这个还在编码测试中

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
注:下文中的 *** 代表文件名中的组件名称。 # 包含: 中文-英文对照文档:【***-javadoc-API文档-中文(简体)-英语-对照版.zip】 jar包下载地址:【***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: 中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值