Разбор документа YAML с картой в корне с помощью snakeYaml
Я хочу прочитать документ YAML на карте пользовательских объектов (вместо карт, которые snakeYaml делает по умолчанию). Так вот:
19:
typeID: 2
limit: 300
20:
typeID: 8
limit: 100
будет загружен на карту, которая выглядит так:
Map<Integer, Item>
где пункт:
class Item {
private Integer typeId;
private Integer limit;
}
Я не мог найти способ сделать это со snakeYaml, и я не мог найти лучшую библиотеку для этой задачи.
в документации есть только примеры с картами / коллекциями, вложенными внутри других объектов, так что вы можно сделать следующее:
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);
но как мне определить формат карты, когда он находится в корне документа?
2 ответов
вам нужно добавить пользовательский конструктор. Однако в вашем случае вы не хотите регистрировать тег "item" или "item-list".
фактически, вы хотите применить Утиной Типизацией к вашему Yaml. Это не очень эффективно, но есть относительно простой способ сделать это.
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);
вот что я сделал для очень похожей ситуации. Я просто вложил весь файл yml на одну вкладку и добавил тег map: наверх. Так и в твоем случае.
map:
19:
typeID: 2
limit: 300
20:
typeID: 8
limit: 100
а затем создайте статический класс в своем классе, который читает этот файл следующим образом.
static class Items {
public Map<Integer, Item> map;
}
а затем, чтобы прочитать карту просто использовать.
Yaml yaml = new Yaml(new Constructor(Items));
Items items = (Items) yaml.load(<file>);
Map<Integer, Item> itemMap = items.map;
обновление:
если вы не хотите или не можете редактировать свой файл yml, вы можете просто выполнить вышеуказанное преобразование в коде во время чтения файл с чем-то вроде этого.
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;
}