dbt
dbt

Reputation: 73

SnakeYAML: How to set bean property type for loading

Using SnakeYAML's TypeDescription, I can add type information about Lists and Maps using:

TypeDescription td = new TypeDescription(MyBean.class, "!mybean");
td.putMapPropertyType("mymap", String.class, MyOtherBean.class);
td.putListPropertyType("mylist", MyOtherBean.class);

This way, I can populate Collections with instances of MyOtherBean without having to rely on any other tags:

---
!mybean
mymap:
  foobar: # will map to an instance of MyOtherBean
    otherbeanprop1: foo
    otherbeanprop2: bar
mylist: # will contain instances of MyOtherBean
  - otherbeanprop1: foo
    otherbeanprop2: bar

Is there any easy way to do something like this:

td.putPropertyType("myotherbean", MyOtherBean.class);

so that the property myotherbean in MyBean would be populated with a single instance of MyOtherBean? Things I am trying to avoid:

I have already played around with this and I think I need to create a custom constructor like this (adapted from the SnakeYAML Documentation):

class SelectiveConstructor extends Constructor {
    public SelectiveConstructor() {
        // define a custom way to create a mapping node
        yamlClassConstructors.put(NodeId.mapping, new ConstructMapping() {
            @Override
            protected Object constructJavaBean2ndStep(MappingNode node, Object object) {
                Class type = node.getType();
                if (type.equals(MyBean.class)) {
                    // something
                    if (propertyname.equals("myotherbean")) {
                        // something
                    }
                } else {
                    // redirect creation to Constructor
                    return super.constructJavaBean2ndStep(node, object);
                }

        }
    }
}

The problem is that I don't really understand what exactly is going on there. Please let me know if there is an easier way. And if there isn't, I would appreciate it if you shared your experience with this.

Upvotes: 1

Views: 3236

Answers (1)

sel-fish
sel-fish

Reputation: 4476

There is an elegant way to do this.
If you don't want to do some special tricks with the YAML content, you can use the following two methods of snakeYaml to dump and load yaml content:

public String dumpAsMap(Object data)              // dump method
public <T> T loadAs(Reader io, Class<T> type)     // load method

In your scenario,

dump :

MyBean bean = new MyBean();
// init bean...
String yamlContent = yaml.dumpAsMap(bean);

load :

FileReader reader = new FileReader(filename);
MyBean bean = yaml.loadAs(reader, MyBean.class);

Of course, you should implement the getter and setter of your classes. For details, you can take a look at the example here.

Upvotes: 2

Related Questions