2013-08-23 3 views
5

SnakeYAML로 사용자 지정 구문을 사용하고 있으며 중첩을 구현하는 방법을 모르겠습니다. 나는 참조 용으로 this example을 사용하고있다.SnakeYAML로 중첩 된 구조

- !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을 변경할 수 링크 된 예에서

, 관련 YAML이며 구축,

- !circle 
    center: !point 
    x: 73 
    y: 129 
    radius: 7 
싶습니다

사용하기 그 !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

뱀야말로 모든 것을 중첩 처리해야합니다. 모든 AbstractConstructs를 사용자 정의 생성자의 yamlConstructors 필드에 추가하면됩니다.

0

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 

어쨌든이 대답이 내 마지막 것보다 조금 더 희망적입니다.