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?

Original source