目录

snakeyaml学习

[TOC]

官方链接

— 1 — 2 — 3

| 和 > 的区别

  • |: 换行
  • >: 空格
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
--- !<tag:clarkevans.com,2002:invoice>
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.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public void testExample_2_27() {
        Yaml yaml = new Yaml(new Constructor(Invoice.class));
        Invoice invoice = (Invoice) yaml.load(Util
                .getLocalResource("specification/example2_27.yaml"));
        assertNotNull(invoice);
        Person billTo = invoice.billTo;
        assertEquals("Dumars", billTo.family);
        yaml = new Yaml();
        String output = yaml.dump(invoice);
        String etalon = Util.getLocalResource("specification/example2_27_dumped.yaml");
        assertEquals(etalon, output);
    }

result:

1
2
3
4
5
6
7
>
lines:  
458 Walkman Dr. Suite #292
|
lines: 
458 Walkman Dr.
Suite #292

还可以使用>>+>-;使用|+|-, 分别表示文末新增一空行,文末新增两空行,文末不新增行

指定转储样式

DumperOptions specifies formatting details for the emitter. For instance, you may set the preferred intendation and width, use the canonical YAML format or force preferred style for scalars and collections.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public void testDumperOptions() {
        List<Integer> data = new ArrayList<Integer>();
        for (int i = 0; i < 50; i++) {
            data.add(i);
        }
        Yaml yaml = new Yaml();
        String output = yaml.dump(data);
        assertTrue(output.contains("[0, 1, 2, 3, 4, 5, 6, 7, 8"));
        //
        DumperOptions options = new DumperOptions();
        options.setWidth(50); // 一行字符数
        options.setIndent(4); // 缩进字符数
        yaml = new Yaml(options);
        output = yaml.dump(data);
        assertTrue(output.contains("1, 2"));
    }

规范输出vs不规范输出

设置规范输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public void testDumperOptionsCanonical() {
    List<Integer> data = new LinkedList<Integer>();
    for (int i = 0; i < 5; i++) {
        data.add(i);
    }
    DumperOptions options = new DumperOptions();
    options.setCanonical(true);
    Yaml yaml = new Yaml(options);
    String output = yaml.dump(data);
    System.out.println(output);
}

输出

1
2
3
4
5
6
7
8
---
!!seq [
  !!int "0",
  !!int "1",
  !!int "2",
  !!int "3",
  !!int "4",
]

设置不规范输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 public void testDumperOptionsFlowStyle() {
        List<Integer> data = new ArrayList<Integer>();
        for (int i = 0; i < 5; i++) {
            data.add(i);
        }
        DumperOptions options = new DumperOptions();
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        Yaml yaml = new Yaml(options);
        String output = yaml.dump(data);
        assertTrue(output.contains("- 0\n"));
        assertTrue(output.contains("- 1\n"));
        assertTrue(output.contains("- 4\n"));
    }

输出:

1
2
3
4
5
- 0
- 1
- 2
- 3
- 4

设置双引号

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public void testDumperOptionsStyle() {
        List<Integer> data = new ArrayList<Integer>();
        for (int i = 0; i < 5; i++) {
            data.add(i);
        }
        DumperOptions options = new DumperOptions();
        options.setDefaultScalarStyle(DumperOptions.ScalarStyle.DOUBLE_QUOTED);
        Yaml yaml = new Yaml(options);
        String output = yaml.dump(data);
        assertTrue(output.contains("- !!int \"0\""));
        assertTrue(output.contains("- !!int \"1\""));
        assertTrue(output.contains("- !!int \"4\""));
    }

输出

1
2
3
4
5
- !!int "0"
- !!int "1"
- !!int "2"
- !!int "3"
- !!int "4"

按照属性名过滤

用途:过滤某些属性

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 public void testFilterPropertyInYaml() {
        BeanToRemoveProperty bean = new BeanToRemoveProperty();
        bean.setNumber(25);
        bean.setId("ID125");
        Yaml yaml = new Yaml(new MyRepresenter());
        String dump = yaml.dumpAsMap(bean);
        // System.out.println(dump);
        assertEquals("number: 25\n", dump);
    }
    
 private class MyRepresenter extends Representer {
        @Override
        protected Set<Property> getProperties(Class<? extends Object> type) {
            Set<Property> set = super.getProperties(type);
            Set<Property> filtered = new TreeSet<Property>();
            if (type.equals(BeanToRemoveProperty.class)) {
                // filter properties
                for (Property prop : set) {
                    String name = prop.getName();
                    if (!name.equals("id")) {
                        filtered.add(prop);
                    }
                }
            }
            return filtered;
        }
    }

按照属性是否为空/empty过滤

测试类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
 public void testSkipNull() {
        Yaml yaml = new Yaml(new SkipNullRepresenter());
        String output = yaml.dump(getBean());
        // System.out.println(output);
        assertEquals(Util.getLocalResource("issues/issue60-1.yaml"), output);
    }

    private class SkipNullRepresenter extends Representer {
        @Override
        protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
                Object propertyValue, Tag customTag) {
            if (propertyValue == null) {
              // 返回null,上层模板方法会continue
                return null;
            } else {
                return super
                        .representJavaBeanProperty(javaBean, property, propertyValue, customTag);
            }
        }
    }

    public void testSkipEmptyCollections() {
        Yaml yaml = new Yaml(new SkipEmptyRepresenter());
        String output = yaml.dump(getBean());
        // System.out.println(output);
        assertEquals(Util.getLocalResource("issues/issue60-2.yaml"), output);
    }

    private class SkipEmptyRepresenter extends Representer {
        @Override
        protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
                Object propertyValue, Tag customTag) {
            NodeTuple tuple = super.representJavaBeanProperty(javaBean, property, propertyValue,
                    customTag);
            Node valueNode = tuple.getValueNode();
            if (Tag.NULL.equals(valueNode.getTag())) {
                return null;// skip 'null' values
            }
            if (valueNode instanceof CollectionNode) {
                if (Tag.SEQ.equals(valueNode.getTag())) {
                    SequenceNode seq = (SequenceNode) valueNode;
                    if (seq.getValue().isEmpty()) {
                        return null;// skip empty lists
                    }
                }
                if (Tag.MAP.equals(valueNode.getTag())) {
                    MappingNode seq = (MappingNode) valueNode;
                    if (seq.getValue().isEmpty()) {
                        return null;// skip empty maps
                    }
                }
            }
            return tuple;
        }
    }

    private SkipBean getBean() {
        SkipBean bean = new SkipBean();
        bean.setText("foo");
        bean.setListDate(null);
        bean.setListInt(Arrays.asList(new Integer[] { null, 1, 2, 3 }));
        bean.setListStr(Arrays.asList(new String[] { "bar", null, "foo", null }));
        return bean;
    }

输出

null则过滤, empty:字段为null或者是list但是没有元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
!!org.yaml.snakeyaml.issues.issue60.SkipBean
empty: []
listInt: [null, 1, 2, 3]
listStr: [bar, null, foo, null]
map: {}
text: foo

!!org.yaml.snakeyaml.issues.issue60.SkipBean
listInt: [null, 1, 2, 3]
listStr: [bar, null, foo, null]
text: foo

转储只读属性

方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 /**
     * Set to true to include read-only JavaBean properties (the ones without
     * setters) in the YAML document. By default these properties are not
     * included to be able to parse later the same JavaBean.
     *
     * @param allowReadOnlyProperties
     *            - true to dump read-only JavaBean properties
     */
    public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
        this.allowReadOnlyProperties = allowReadOnlyProperties;
    }

test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  public void testDoNotFilterPropertyIncludeReadOnly() {
        BeanToRemoveProperty bean = new BeanToRemoveProperty();
        bean.setNumber(26);
        bean.setId("ID126");
        DumperOptions options = new DumperOptions();
        options.setAllowReadOnlyProperties(true);
        Yaml yaml = new Yaml(options);
        String dump = yaml.dump(bean);
        // System.out.println(dump);
        assertEquals(
                "!!org.yaml.snakeyaml.representer.FilterPropertyToDumpTest$BeanToRemoveProperty {id: ID126,\n  number: 26, something: true}\n",
                dump);
    }

public class BeanToRemoveProperty {
        private int number;
        private String id;

        public boolean isSomething() {
            return true;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }
    }

可以看到BeanToRemoveProperty只有isSomething方法,但是转储时也会有something属性

转储时设置对象属性按照属性顺序输出而不是按照字典顺序

测试类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    public void testUnsorted() {
        Representer repr = new Representer();
        repr.setPropertyUtils(new UnsortedPropertyUtils());
        Yaml yaml = new Yaml(repr);
        String output = yaml.dump(getBean());
        // System.out.println(output);
        assertEquals(Util.getLocalResource("issues/issue59-2.yaml"), output);
    }

    private class UnsortedPropertyUtils extends PropertyUtils {
        @Override
        protected Set<Property> createPropertySet(Class<? extends Object> type, BeanAccess bAccess) {
            Set<Property> result = new LinkedHashSet<Property>(getPropertiesMap(type,
                    BeanAccess.FIELD).values());
//            result.remove(result.iterator().next());// drop 'listInt' property
            return result;
        }
    }

对象

1
2
3
4
5
6
7
8
9
public class SkipBean {

    private List<Integer> listInt;
    private List<String> listStr;
    private List<Date> listDate;
    private List<File> empty = new ArrayList<File>(0);
    private Map<String, Integer> map = new HashMap<String, Integer>(0);
    private String text;
    private Integer number;

输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
!!org.yaml.snakeyaml.issues.issue60.SkipBean
listInt: [null, 1, 2, 3]
listStr: [bar, null, foo, null]
listDate: null
empty: []
map: {}
text: foo
number: null


如果不是按照顺序
!!org.yaml.snakeyaml.issues.issue60.SkipBean
empty: []
listDate: null
listInt: [null, 1, 2, 3]
listStr: [bar, null, foo, null]
map: {}
number: null
text: foo

使用模板引擎渲染yaml

Since a YAML document is nothing but a text document any Template processor can be used.

由于 YAML 文档只不过是文本文档,因此可以使用任何模板处理器。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class VelocityTest extends TestCase {
    public void testNoTemplate() {
        DumperOptions options = new DumperOptions();
        options.setAllowReadOnlyProperties(true);
        Yaml yaml = new Yaml(options);
        String output = yaml.dumpAsMap(createBean());
        // System.out.println(output);
        assertEquals(Util.getLocalResource("template/etalon1.yaml"), output);
    }

    public void testTemplate1() throws Exception {
        VelocityContext context = new VelocityContext();
        MyBean bean = createBean();
        context.put("bean", bean);
        Yaml yaml = new Yaml();
        context.put("list", yaml.dump(bean.getList()));
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty("file.resource.loader.class", ClasspathResourceLoader.class.getName());
        ve.init();
        Template t = ve.getTemplate("template/mybean1.vm");
        StringWriter writer = new StringWriter();
        t.merge(context, writer);
        String output = writer.toString().trim().replaceAll("\\r\\n", "\n");
        // System.out.println(output);
        String etalon = Util.getLocalResource("template/etalon2-template.yaml").trim();
        assertEquals(etalon.length(), output.length());
        assertEquals(etalon, output);
        // parse the YAML document
        Yaml loader = new Yaml();
        MyBean parsedBean = loader.loadAs(output, MyBean.class);
        assertEquals(bean, parsedBean);
    }

    private MyBean createBean() {
        MyBean bean = new MyBean();
        bean.setId("id123");
        List<String> list = new ArrayList<String>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        bean.setList(list);
        Point p = new Point(1.0, 2.0);
        bean.setPoint(p);
        return bean;
    }
}

感叹号个数

您可以使用一个感叹号,表示自定义对象/类型看,和两个感叹号以指示明确的内置类型。