2017-06-15 28 views
0

我已經在程序中下面的類結構,我無法改變:SnakeYAML:創建某些對象不同

class Node { 
    public String name; 
} 

class Nodes { 
    public List<Node> nodes; 
} 

class Master { 
    public Nodes nodes; 
} 

我可以使用下面的YAML來初始化它:

master: 
    nodes: 
    nodes: 
     - name: test 

有什麼SnakeYaml可能會用某種自定義對象實例化邏輯省略第一個「節點:」,這樣我的客戶就可以使用下面的YAML?

master: 
    nodes: 
    - name: test 

我試圖用一個自定義的構造函數實現,但並沒有得到這方面的工作:

class MyConstructor extends Constructor { 
    MyConstructor() { 
     yamlClassConstructors.put(NodeId.mapping, new NodesConstructor()); 
    } 

    class NodesConstructor extends Constructor.ConstructMapping { 
     @Override 
     protected Object constructJavaBean2ndStep(MappingNode node, Object object) { 
      Class type = node.getType(); 

      if (type.equals(Master.class)) { 
       Nodes nodes = new Nodes(); 
       //FIXME: I don't want to construct the whole object tree here, I only want to fill the nodes 
       nodes.nodes = new ArrayList<>(); 
       Master master = new Master(); 
       master.nodes = nodes; 
       return master; 
      } else { 
       return super.constructJavaBean2ndStep(node, object); 
      } 
     } 
    } 
} 

最後,這是我希望得到的工作:

class MyDsl { 
    public Master master; 
} 

public class SnakeYaml { 
    public static void main(String[] args) throws IOException { 
     // 1: this is working OK 
     Yaml yaml = new Yaml(); 
     MyDsl myDsl = yaml.loadAs("master:\n nodes:\n nodes:\n  - name: mystage", MyDsl.class); 
     if(!myDsl.master.nodes.nodes.get(0).name.equals("mystage")) { 
      throw new AssertionError("Failed with nested nodes"); 
     } 

     // 2: this is how I need it 
     Yaml yaml2 = new Yaml(new MyConstructor()); 
     MyDsl myDsl2 = yaml2.loadAs("master:\n nodes:\n - name: mystage", MyDsl.class); 
     if(!myDsl2.master.nodes.nodes.get(0).name.equals("mystage")) { 
      throw new AssertionError("Failed with leaving out nodes"); 
     } 
    } 
} 

有任何想法嗎?提前致謝。

+0

爲什麼不預處理YAML文件並刪除中間'nodes'。這將需要約5行的Python程序。 – Anthon

+0

謝謝。雖然這將是一個選項,但我正在尋找一種方法來實現它與SnakeYAML本身。此外,我也想從一個對象樹中生成這個YAML(沒有中間節點)。我認爲肯定有辦法,到目前爲止我只能找到它...... –

回答

0

我終於做到了,解決這個問題是手動改變底層的地圖,它轉儲到一個字符串,並與我的DSL包裝類再次裝入:

Yaml yaml2 = new Yaml(); 
Map map = yaml2.loadAs("master:\n nodes:\n - name: mystage", Map.class); 
Map master = (Map) map.get("master"); 
List nodes = (List) master.get("nodes"); 
Map newNodes = new HashMap(); 
newNodes.put("nodes", nodes); 
master.put("nodes", newNodes); 
String modifiedDsl = yaml.dump(map); 
MyDsl myDsl2 = yaml2.loadAs(modifiedDsl, MyDsl.class); 

也許不是最漂亮的解決方案,但有用。還有一個問題是如何在另一個方向上使用它(爲DSL對象生成YAML)。