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
支援從
String
或
InputStream
加載文檔
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);
}
2 載入多個檔案
假設下面的内容在一個檔案中:
---
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'