Parsing a YAML document with a map in the root using snakeYaml

I want to read a YAML document on a map of user objects (instead of maps that make snakeYaml by default). So:

19: typeID: 2 limit: 300 20: typeID: 8 limit: 100 

It will be downloaded to a card that looks like this:

 Map<Integer, Item> 

where Item:

 class Item { private Integer typeId; private Integer limit; } 

I could not find a way to do this with snakeYaml, and I also could not find a better library for this task.

There are only examples in the documentation with maps / collections nested in other objects, so 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 can I determine the format of the map when it is in the root directory of the document?

+6
source share
2 answers

You need to add a custom Constructor . However, in your case, you do not want to register the tag "item" or "item-list".

Essentially, you want to apply Duck Typing to your Barley. This is 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); 
+2
source

Here is what I did for a very similar situation. I just nested the whole yml file in one tab and added a map label: at the top. So for your business it will be.

 map: 19: typeID: 2 limit: 300 20: typeID: 8 limit: 100 

And then create a static class in your class that reads this file as shown below.

 static class Items { public Map<Integer, Item> map; } 

And then, to read your card, just use.

 Yaml yaml = new Yaml(new Constructor(Items)); Items items = (Items) yaml.load(<file>); Map<Integer, Item> itemMap = items.map; 

UPDATE:

If you do not want or cannot edit your yml file, you can simply perform the above conversion in code when reading a file with something like this.

 try (BufferedReader br = new BufferedReader(new FileReader(new File("example.yml")))) { StringBuilder builder = new StringBuilder("map:\n"); String line; while ((line = br.readLine()) != null) { builder.append(" ").append(line).append("\n"); } Yaml yaml = new Yaml(new Constructor(Items)); Items items = (Items) yaml.load(builder.toString()); Map<Integer, Item> itemMap = items.map; } 
+3
source

Source: https://habr.com/ru/post/982575/


All Articles