2013-08-23 6 views
5

私はSnakeYAMLでカスタムコンストラクタを使用していますが、ネストを実装する方法がわかりません。私は参考としてthis exampleを使用しています。リンクされている例でSnakeYAMLをネストしたコンストラクタ

、関連YAMLと構築され、

- !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; 
    } 
} 

それでは、

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

にYAMLを変更してみましょう私が使用したいですその!pointオブジェクトを解析する別のAbstractConstructがありますが、ConstructCircleコンテキスト。 Construct/Nodeの関係についての私の理解はかなり不安定で、私はカスタムコンストラクタ内でカスタムコンストラクタを使用する方法を失っています。どんな考えやリソース?

答えて

0

Nested Constructs YAMLを解析するために、素早く汚れたcustomConstructMapping()を書きました。

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; 
} 
0

スネーク・ヤムルは、すべてそれ自身をネストする必要があります。カスタムコンストラクタ内のyamlConstructorsフィールドにすべての抽象コンストラクタを確実に追加する必要があります。

0

SnakeYamlでもう少しプロジェクトをやってみてください。私は最終的にあなたの質問を理解すると思います。ネスティングはSnakeYamlによって自動的に処理されます。あなたはそれについて心配する必要はありません。 !ポイント用の別のコンストラクトを作成し、それをカスタムコンストラクタクラスの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 

また、新しいコンストラクトを作成するのをやめて、PointにBeanパターンに従い、このようなものを使用することもできます。

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

とにかくこの回答が私の最後のものより少しはっきりしていることを願っています。

関連する問題