【问题标题】:Get Integer[] instead of ArrayList<Integer> from YAML file从 YAML 文件中获取 Integer[] 而不是 ArrayList<Integer>
【发布时间】:2017-01-16 21:21:30
【问题描述】:

我正在解析一个 YAML 文件

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

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

【问题讨论】:

  • 没有。 “还有 12 个……”
  • @StephanBijzitter 你能详细说明一下吗?
  • 获取 List 还是数组是由解析 YAML 的库做出的决定,而不是 YAML 文档本身的特性。
  • 我正在使用snakeYaml,这个库是否提供自定义配置?是否有任何其他库提供它返回的类型的自定义配置?
  • 向我们展示您如何进行反序列化。

标签: java arrays arraylist yaml snakeyaml


【解决方案1】:

与我的其他答案相比,这个答案侧重于更改 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);

【讨论】:

  • 我正在尝试使用 yamlClassConstructors.put(NodeId.sequence, new AbstractConstruct() { @Override public Integer[] construction(Node node) { List<integer> list = (List)constructSequence((SequenceNode)node); return list.toArray(new Integer[list.size()]); } };); 而不是自定义标签。但它返回 ArrayList,可能永远不会被使用。
  • 有趣。您是否尝试调试它以检查它是否被调用?这个方法被描述为here,所以它应该可以工作。
  • 尝试从 ConstructSequence 继承而不是 AbstractConstruct 并覆盖 construct2ndStep,类似于 Howto。
  • construct(Node node) 从未被调用过!
  • useClassConstructor in Node 返回 false!
【解决方案2】:

来自snakeyaml 文档:

Default implementations of collections are:

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

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

【讨论】:

    【解决方案3】:

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

    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 文件不稳定,prop 可以是数组,也可以是 int、double 等。
    猜你喜欢
    • 2021-03-21
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    • 2013-06-09
    相关资源
    最近更新 更多