使用snakeyaml Library在Java中将对象序列化为YAML

时间:2011-12-13 11:32:11

标签: java serialization snakeyaml

我对序列化没有多少经验。在尝试序列化下面类的一个简单对象时,我从YAML库中获取此No JavaBean properties found exception

这是班级:

public class MyClass {
    String value;
    public MyClass(String args) {
        value = args;
    }

    public String getValue(){
        return value;
    }
}

以下是我使用SnakeYAMAL进行序列化的方法:

import java.util.HashMap;
import java.util.Map;

import org.yaml.snakeyaml.Yaml;


public class Test {

    public static void main(String[] args) {

        MyClass obj = new MyClass("this is my data");

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("MyClass", obj);
        Yaml yaml = new Yaml();
        String output = yaml.dump(data);
        System.out.println(output);
    }

}

并在执行时抛出此异常:

Exception in thread "main" org.yaml.snakeyaml.error.YAMLException: No JavaBean properties found in MyClass
    at org.yaml.snakeyaml.introspector.PropertyUtils.getProperties(PropertyUtils.java:112) ...

你能告诉我在这样做时我缺少什么,或者我该怎么做呢?

编辑:

public class MyClass {
    String value;
    public MyClass() {}

    public String setValue(String value){
        this.value = value;
    }

    public String getValue(){
        return value;
    }
}

如果我在序列化之前设置了值,它会以某种方式工作。 您认为这是正确的解决方案还是不推荐的方法?

1 个答案:

答案 0 :(得分:10)

SnakeYAML主要用于序列化JavaBeans。

上面给出的示例不符合JavaBean规范。要成为JavaBean,对象必须具有无参数构造函数,并且每个字段都必须具有getter和setter。

如果您将类重写为bean,SnakeYAML应该没有问题地序列化它。此外,SnakeYAML可以序列化公共字段,因此如果您将value的可见性更改为public,则SnakeYAML会查找并序列化它。

如果你真的想避免改变MyClass,你可以明确告诉SnakeYAML序列化只读属性,如下所示:

PropertyUtils propUtils = new PropertyUtils();
propUtils.setAllowReadOnlyProperties(true);
Representer repr = new Representer();
repr.setPropertyUtils(propUtils);
Yaml yaml = new Yaml(new Constructor(), repr);

但是,将非JavaBean对象转储到YAML可能会在将它们反序列化回Object时导致问题,所以我建议使用JavaBeans作为最简单和最安全的解决方案。

编辑:以下是转换为JavaBean的MyClass示例:

public class MyClass {
    String value;

    /* public, no-argument constructor */
    public MyClass() {
    }

    /* Every field has a public getter... */
    public String getValue(){
        return value;
    }

    /* ... and a public setter */
    public void setValue(String value) {
        this.value = value;
    }
}