Parsing a YAML document with a map at the root using snakeYaml
java, snakeyaml, yaml
Solution
You need to add a custom Constructor. However, in your case you don't want register an "item" or "item-list" tag.
In effect, you want to apply Duck Typing to your Yaml. It's not super efficient, but there is a relatively easy way to do this.
class YamlConstructor extends Constructor {
@Override
protected Object constructObject(Node node) {
if (node.getTag() == Tag.MAP) {
LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) super
.constructObject(node);
// If the map has the typeId and limit attributes
// return a new Item object using the values from the map
...
}
// In all other cases, use the default constructObject.
return super.constructObject(node);
Problem
I want to read a YAML document to a map of custom objects (instead of maps, which snakeYaml does by default). So this: ``` 19: typeID: 2 limit: 300 20: typeID: 8 limit: 100 ``` Would be loaded to a map which looks like this: ``` Map<Integer, Item> ``` where Item is: ``` class Item { private Integer typeId; private Integer limit; } ``` I could not find a way to do this with snakeYaml, and I couldn't find a better library for the task either. The documentation only has examples with maps/collections nested inside other objects, so that you can do the following: ``` TypeDescription typeDescription = new TypeDescription(ClassContainingAMap.class); typeDescription.putMapPropertyType("propertyNameOfNestedMap", Integer.class, Item.class); Constructor constructor = new Constructor(typeDescription); Yaml yaml = new Yaml(constructor); /* creating an input stream (is) */ ClassContainingAMap obj = (ClassContainingAMap) yaml.load(is); ``` But how do I go about defining the Map format when it is at the root of the document?