2017-04-10 85 views
0

我有這樣一組抽象類:反序列化XML動態創建的類在Java中

abstract class A { 
    public abstract B getB() {return this.b;} 

    public abstract void setB(B b) {this.b = b;} 
} 

abstract class B { 
    public abstract C getC() {return this.c;} 

    public abstract void setC(C c) {this.c = c;} 
} 

abstract class C { 
    private String foo; 

    public String getFoo() {return this.foo;} 

    public void setFoo(String foo) {this.foo = foo;} 
} 

在運行時,我創建了使用ByteBuddy這些類代理。我可以輕鬆地將這些代理類的對象序列化爲XML。但是當我試圖反序列化XML時,JAXB會拋出javax.xml.bind.UnmarshalException: Unable to create an instance of A,因爲它無法創建抽象類的實例。我想告訴它如何在運行時創建這些實例以反序列化它們(我有一個特殊的Spring bean,這是它 - 所以我需要能夠注入它,無論我在哪裏定義創建邏輯)我看着JAXB和Jackson ,但無法找到如何去做。

有沒有辦法做到這一點?我沒有被綁定到任何序列化框架,儘管最好留在JAXB或者傑克遜。

+0

你能展示一個樣本xml嗎? – Ishnark

回答

0

我發現,無論是JAXB和傑克遜能做到這一點。

JAXB提供了兩種解決方法:工廠方法和適配器。

  1. 使用JAXB工廠方法,我需要建立一個工廠,將負責創建對象:

    public class MyFactory { 
        public static MyObject createMyObject() { 
         return SomeMagic.createMyObject(); 
        } 
    } 
    

    然後,我只需要記住我的抽象類@XmlType註釋:

    @XmlType(factoryClass = MyFactory.class, factoryMethod = "createMyObject") 
    public abstract class MyObject { 
        ... 
    } 
    
  2. 如果我想使用JAXB適配器,我將需要創建JAXB可以實例,並從XML填寫Java類,然後我需要CONV這些類的給那些ERT對象,我需要:

    public class MyAdapter extends XmlAdapter<MyAdapter.MyJaxbObject, MyObject> { 
        @Override 
        public MyObject unmarshal(MyJaxbObject src) throws Exception { 
         MyObject tgt = SomeMagic.createMyObject(); 
         BeanUtils.copyProperties(tgt, src); 
         return tgt; 
        } 
    
        @Override 
        public MyObject marshal(MyObject src) throws Exception { 
         MyJaxbObject tgt = new MyJaxbObject(); 
         BeanUtils.copyProperties(tgt, src); 
         return tgt; 
        } 
    
        public static class MyJaxbObject { 
         ... 
        } 
    } 
    

    然後,我會記住我的抽象類@XmlJavaAdapter註釋:

    @XmlJavaAdapter(MyAdapter.class) 
    public abstract class MyObject { 
        ... 
    } 
    
  3. 使用傑克遜,我可以創造我的抽象類的自定義解串器。

    public class MyObjectDeserializer extends StdDeserializer<MyObject> { 
        public MyObjectDeserializer() { 
         super(MyObject.class); 
        } 
    
        @Override 
        public MyObject deserialize(JsonParser parser, DeserializationContext context) throws IOException { 
         ObjectMapper mapper = (ObjectMapper) parser.getCodec(); 
         MyObject myObject = SomeMagic.createMyObject(); 
         return mapper.readerForUpdating(myObject).readValue(parser); 
        } 
    } 
    

    在我的代碼後來我需要註冊我的解串器:

    ObjectMapper mapper = new XmlMapper(); 
    SimpleModule module = new SimpleModule("module", new Version(1, 0, 0, null, null, null)); 
    module.addDeserializer(MyObject.class, new MyObjectDeserializer()); 
    mapper.registerModule(module); 
    

對於我而言我更喜歡傑克遜定製的解串器,這是因爲:

  1. 我還需要執行嵌套對象的字段被填充之後但在將這些對象傳遞給其他對象的setter之前對其進行額外操作(JAXB似乎不支持t it)
  2. 我可以使用自定義邏輯當我填寫對象的字段(也可以用適配器實現)。
  3. 我可以自己創建反序列化器,所以我可以使用依賴注入來配置它們(工廠是靜態的,而適配器是由JAXB創建的)。