从 YAML 文件中获取 Integer[] 而不是 ArrayList<Integer>

Get Integer[] instead of ArrayList<Integer> from YAML file

我正在解析 YAML 文件

Props:
  Prop1 : [10, 22, 20]
  Prop2 : [20, 42, 60]

这给了我 Map<String, Map<String, ArrayList<Integer>>> 我想得到 Map<String, Map<String, Integer[]>> 我不想在读取文件的代码中转换 List<Integer> to Integer[]。我可以更改我的 YAML 文件中的内容吗?

来自 snakeyaml 文档:

Default implementations of collections are:

 - List: ArrayList 
 - Map: LinkedHashMap (the order is implicitly defined)

没有简单的方法来改变它。只需在列表中调用 toArray() 即可。

如果你的 YAML 文件的布局是稳定的,你可以将它直接映射到一个 Java class,它定义了内部属性的类型:

public class Props {
    public Integer[] prop1;
    public Integer[] prop2;
}

public class YamlFile {
    public Props props;
}

然后,你可以这样加载:

final Yaml yaml = new Yaml(new Constructor(YamlFile.class));
final YamlFile content = (YamlFile) yaml.load(myInput);
// do something with content.props.prop1, which is an Integer[]

我为属性使用了标准 Java 命名,这需要您将 YAML 文件中的键更改为小写:

props:
  prop1 : [10, 22, 20]
  prop2 : [20, 42, 60]

您也可以保留大写字母,但您需要相应地重命名 Java 属性。

与我的另一个答案相反,这个答案侧重于更改 YAML 文件。但是,您还需要添加一些 Java 代码来告诉 SnakeYaml 如何加载您使用的标签。

您可以向 YAML 序列添加标签:

Props:
  Prop1 : !intarr [10, 22, 20]
  Prop2 : !intarr [20, 42, 60]

加载前需要在SnakeYaml注册:

public class MyConstructor extends Constructor {
    public MyConstructor() {
        this.yamlConstructors.put(new Tag("!intarr"),
                                  new ConstructIntegerArray());
    }

    private class ConstructIntegerArray extends AbstractConstruct {
        public Object construct(Node node) {
            final List<Object> raw = constructSequence(node);
            final Integer[] result = new Integer[raw.size()];
            for(int i = 0; i < raw.size(); i++) {
                result[i] = (Integer) raw.get(i);
            }
            return result;
        }
    }
}

你这样使用它:

Yaml yaml = new Yaml(new MyConstructor());
Map<String, Map<String, Integer[]>> content =
    (Map<String, Map<String, Integer[]>>) yaml.load(myInput);