2017-04-10 69 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创建的)。