2016-02-13 100 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); 
     } 
    } 
}