【问题标题】:Nested Constructs with SnakeYAML使用 SnakeYAML 的嵌套构造
【发布时间】:2013-08-27 02:08:05
【问题描述】:

我正在考虑使用带有 SnakeYAML 的自定义构造,但不确定如何实现嵌套。我使用this example 作为参考。

在链接的例子中,相关的 YAML 和 Construct 是,

- !circle
  center: {x: 73, y: 129}
  radius: 7

private class ConstructCircle extends AbstractConstruct {
    @SuppressWarnings("unchecked")
    public Object construct(Node node) {
        MappingNode mnode = (MappingNode) node;
        Map<Object, Object> values = constructMapping(mnode);
        Circle circle = new Circle((Map<String, Integer>) values.get("center"), (Integer) values.get("radius"));
        return circle;
    }
}

现在,让我们将 YAML 更改为,

- !circle
  center: !point
    x: 73
    y: 129
  radius: 7

我想使用另一个AbstractConstruct 来解析该!point 对象,但在ConstructCircle 上下文中进行。我对Construct/Node 关系的理解非常不稳定,我不知道如何在自定义构造函数中使用自定义构造函数。有什么想法或资源吗?

【问题讨论】:

    标签: java yaml snakeyaml


    【解决方案1】:

    在使用 SnakeYaml 完成更多项目后,好吧。我想我终于明白你的问题了。嵌套由 SnakeYaml 自动处理。您无需担心这一点。您需要做的就是为 !point 创建另一个 Construct,并将其添加到自定义构造函数类中的地图 yamlConstructors 中。这将在任何地方启用 !point 标签。

    点构造可能如下所示:

    class PointConstruct extends AbstractConstruct{
       public Object construct(Node node){
          String line = (String)constructScalar((ScalarNode)node);
          Pattern pointPattern = Pattern.compile("\\((\\d+),(\\d+\\)");
          Matcher m = pointPattern.matcher(line);
          if(m.find())
             return new Point(m.group(1),m.group(2));
          throw new RuntimeException("Could not parse a point");
       }
    }
    

    您的 Yaml 文件将如下所示:

    !circle
    center: !point (73,179)
    radius: 7
    

    我认为这个输出看起来好多了。如果在 yaml 中添加 ImplicitResolver:

    yaml.addImplicitResolver(new Tag("!point"), Pattern.compile("\\((\\d+),(\\d+\\)"),"(");
    

    那么 yaml 将如下所示。

    !circle
    center: (73,179)
    radius: 7
    

    或者,您可以放弃编写新的 Construct 并让 Point 遵循 bean 模式并使用类似的东西。

    !circle
    center !!package.goes.here.Point
      x: 73
      y: 179
    radius: 7
    

    无论如何希望这个答案比我上一个答案更清楚。

    【讨论】:

      【解决方案2】:

      我写了一个快速而肮脏的customConstructMapping() 来解析您的嵌套构造 YAML。

      public Map<Object, Object> customConstructMapping(MappingNode mnode) {
          Map<Object, Object> values = new HashMap<Object, Object>();
          Map<String, Integer> center = new HashMap<String, Integer>();
          List<NodeTuple> tuples = mnode.getValue();
          for (NodeTuple tuple : tuples) {
              ScalarNode knode = (ScalarNode) tuple.getKeyNode();
              String key = knode.getValue();
      
              Node vnode = tuple.getValueNode();
              if (vnode instanceof MappingNode) {
                  MappingNode nvnode = (MappingNode) vnode;
                  if ("!point".equals(nvnode.getTag().getValue())) {
                      List<NodeTuple> vtuples = nvnode.getValue();
                      for (NodeTuple vtuple : vtuples) {
                          ScalarNode vknode = (ScalarNode) vtuple.getKeyNode();
                          ScalarNode vvnode = (ScalarNode) vtuple.getValueNode();
                          Integer val = Integer.parseInt(vvnode.getValue());
                          center.put(vknode.getValue(), val);
                      }
                      values.put(key, center);
                  }
              } else if (vnode instanceof ScalarNode) {
                  Integer val = Integer.parseInt(((ScalarNode) vnode).getValue());
                  values.put(key, val);
              }
          }
          return values;
      }
      

      【讨论】:

        【解决方案3】:

        Snake Yaml 应该自己处理所有的嵌套。您只需确保将所有 AbstractConstructs 添加到自定义构造函数内的 yamlConstructors 字段中。

        【讨论】:

          猜你喜欢
          • 2019-12-18
          • 1970-01-01
          • 1970-01-01
          • 2021-05-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-26
          • 1970-01-01
          相关资源
          最近更新 更多