使用snakeYaml在根部解析带有地图的YAML文档

Jus*_*tas 9 java yaml snakeyaml

我想将YAML文档读取到自定义对象的地图(而不是地图,默认情况下是snakeYaml执行的).所以这:

19:
  typeID: 2
  limit: 300
20:
  typeID: 8
  limit: 100
Run Code Online (Sandbox Code Playgroud)

将被加载到如下所示的地图:

Map<Integer, Item>
Run Code Online (Sandbox Code Playgroud)

其中项目是:

class Item {
    private Integer typeId;
    private Integer limit;
}
Run Code Online (Sandbox Code Playgroud)

我找不到使用snakeYaml做到这一点的方法,我也找不到更好的任务库.

该文档仅包含嵌套在其他对象中的maps/collections的示例,以便您可以执行以下操作:

    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);
Run Code Online (Sandbox Code Playgroud)

但是,当它位于文档的根目录时,如何定义Map格式呢?

cro*_*umb 8

这是我为一个非常相似的情况所做的.我只是将整个yml文件标记在一个选项卡上,并在顶部添加了map:标记.所以对你的情况来说就是这样.

map:
  19:
    typeID: 2
    limit: 300
  20:
    typeID: 8
    limit: 100
Run Code Online (Sandbox Code Playgroud)

然后在类中创建一个静态类,读取此文件,如下所示.

static class Items {
    public Map<Integer, Item> map;
}
Run Code Online (Sandbox Code Playgroud)

然后阅读你的地图就好用.

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

更新:

如果您不想或不能编辑您的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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您需要添加一个自定义的Constructor。但是,在您的情况下,您不想注册“项目”或“项目列表”标签。

实际上,您希望将Duck Typing应用到您的 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);
Run Code Online (Sandbox Code Playgroud)

  • 哇,Java 中的 YAML 支持令人震惊。虽然这个解决方案有效,但在处理嵌套结构时会很头疼。我想我会将所有内容都转换为 JSON 并使用 Jackson 进行解析。 (9认同)
  • 是的。java (/scala) 中的 Yaml 解析 * 太糟糕了。来自python,它是“免费的”。 (2认同)