2016-02-13 49 views
0

我想要marshall和unmarshall對象的字段是其類的內部類(合成類,如果我沒有錯的話)。Xstream:解組內部類

class A { 
    private B field_b=null; 
    public static class B { 
     public static B B1 = new B("b1"); 
     public static B B2 = new B("b2"); 

     private final String name; 
     private B(String name) { 
      this.name=name; 
      } 
     } 
    public B getBforName(String name) { 
     if (B1.name.equals(name) return B1;    
     else if (B2.name.equals(name) return B2; 
     else return null;    
    } 

而產生,並從一個XML閱讀:

<A> 
    <field_B>b1</field_B> 
</A> 

寫入的部分是很容易。

閱讀部分比較複雜。

我想編寫一個轉換器:

public class BConverter implements Converter { 
    public boolean canConvert(Class type) { 
     return B.class.isAssignableFrom(type) ; 
    } 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     // ... 
    } 
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
     A parent_v1 = (A) context.getCurrentObject(); // !!! always empty 
     A parent_v2 = (A) context.get("current_unmarshalled_A"); 

     return parent_v2.getBforName((String)reader.getValue()); 

    } 
} 

context.getCurrentObject()返回null,似乎是過時的(從論壇我讀)。

context.get("current_unmarshalled_A")將要求我把這個unMarshallingContext這個鍵和A對象解組。如果不寫AConverter,我不會這麼做。這不是整齊的,因爲我會失去A級的默認解組行爲。

任何人都有想法嗎?

回答

0

我不確定這是最乾淨的方式,但它的工作原理。

我在B類中使用一個靜態方法...

class A { 
    private B field_b=null; 
    public static class B { 
     public static B B1 = new B("b1"); 
     public static B B2 = new B("b2"); 

     public static B getForName(String name) { 
      if (B1.name.equals(name) return B1;    
      else if (B2.name.equals(name) return B2; 
      else return null;    
     } 

     private final String name; 
     private B(String name) { 
      this.name=name; 
      } 
    } 

...,並在轉換器反射

public class BConverter implements Converter { 
    public boolean canConvert(Class type) { 
     return B.class.isAssignableFrom(type) ; 
    } 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     writer.setValue(((B)source).getName()) 
    } 
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
     try { 
      Method method = context.getRequiredType().getMethod("getForName", String.class); 
      final String v = reader.getValue(); 
      Object b= method.invoke(null, v); 
      if (b== null) 
       throw new ConversionException("Could not retrieve a B object for \"" + v + "\""); 
      return b; 
     } catch (Exception ex) { 
      throw new ConversionException("Error while retrieving a B object", ex); 
     } 
    } 
}