2013-08-23 37 views
5

Tôi đang xem xét việc sử dụng các cấu trúc tùy chỉnh với SnakeYAML và không chắc chắn cách triển khai lồng nhau. Tôi đang sử dụng this example làm tài liệu tham khảo.Xây dựng lồng nhau với SnakeYAML

Trong ví dụ liên kết, các YAML liên quan và Xây dựng là,

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

Bây giờ, chúng ta hãy thay đổi YAML đến,

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

Tôi muốn sử dụng một số khác AbstractConstruct để phân tích cú pháp đối tượng !point đó nhưng thực hiện trong phạm vi ConstructCircle ngữ cảnh. Sự hiểu biết của tôi về mối quan hệ Construct/Node là khá run rẩy và tôi đang thua lỗ về cách sử dụng một hàm tạo tùy chỉnh trong một hàm tạo tùy chỉnh. Bất kỳ suy nghĩ hoặc tài nguyên nào?

Trả lời

0

Tôi đã viết customConstructMapping() nhanh chóng và bẩn để phân tích cú pháp Nested Constructs YAML của bạn.

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

Con rắn Yaml nên tự chăm sóc làm tổ. Bạn chỉ cần chắc chắn để thêm tất cả các AbstractConstructs của bạn vào trường yamlConstructors bên trong Custom Constructor của bạn.

0

Được rồi sau khi thực hiện thêm một vài dự án với SnakeYaml. Tôi nghĩ cuối cùng tôi đã hiểu câu hỏi của bạn. Làm tổ được lấy tự động bởi SnakeYaml. Bạn không cần phải lo lắng về điều đó. Tất cả những gì bạn cần làm là tạo một Construct khác cho điểm !, và thêm nó vào bản đồ yamlConstructors trong lớp constructor tùy chỉnh của bạn. Điều này sẽ kích hoạt thẻ điểm!

các cấu trúc điểm có thể giống như thế này:

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"); 
    } 
} 

file YAML của bạn sau đó sẽ trông như thế này:

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

tôi nghĩ ra điều này có vẻ đẹp hơn rất nhiều. Nếu bạn thêm một ImplicitResolver vào yaml:

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

Sau đó, yaml sẽ trông như thế này.

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

Hoặc bạn có thể từ bỏ viết một Cấu trúc mới và chỉ cần có điểm theo mẫu đậu và sử dụng một cái gì đó như thế này.

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

anyway Hy vọng câu trả lời này rõ ràng hơn một chút so với lần cuối cùng của tôi.

Các vấn đề liên quan