2012-03-06 83 views
7

我想使用JAXB解組一些XML,但我得到「無法創建一個......的實例」異常。我明白爲什麼 - 它試圖創建一個抽象類的實例。我想要的是讓它創建一個特定的實現類的實例。我的目標是對setter方法進行類特定檢查。也許「qux」對BarImpl來說是一個有效的baz值,但BarImpl2想要做其他事情。JAXB和抽象類

通過不註釋Foo,我得到了部分途徑,但如果我unannotate欄,事情變得醜陋。

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

import org.junit.Test; 


public class JAXBTest { 

    @Test 
    public void test() throws javax.xml.bind.JAXBException { 
     String xml = 
      "<foo>" + 
      " <bar>" + 
      " <baz>qux</baz>" + 
      " </bar>" + 
      "</foo>"; 

     javax.xml.bind.JAXBContext context = javax.xml.bind.JAXBContext.newInstance(
       FooImpl.class, 
       BarImpl.class 
     ); 

     javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller(); 

     unmarshaller.unmarshal(new java.io.StringReader(xml)); 
    } 

    @XmlRootElement(name="foo") 
    public static abstract class Foo { 
     @XmlElement(name="bar") 
     Bar bar; 
    } 

    @XmlRootElement(name="bar") 
    public static abstract class Bar { 
     @XmlElement(name="baz") 
     String baz; 
    } 

    public static class FooImpl extends Foo { } 
    public static class BarImpl extends Bar { } 
} 

回答

14

你可以做到以下幾點:

JAXBTest

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElements; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlTransient; 

import org.junit.Test; 


public class JAXBTest { 

    @Test 
    public void test() throws javax.xml.bind.JAXBException { 
     String xml = 
      "<foo>" + 
      " <bar>" + 
      " <baz>qux</baz>" + 
      " </bar>" + 
      "</foo>"; 

     javax.xml.bind.JAXBContext context = javax.xml.bind.JAXBContext.newInstance(
       FooImpl.class, 
       BarImpl.class 
     ); 

     javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller(); 

     unmarshaller.unmarshal(new java.io.StringReader(xml)); 
    } 

    @XmlTransient 
    public static abstract class Foo { 
     @XmlElements({ 
      @XmlElement(name="bar",type=BarImpl.class), 
      @XmlElement(name="bar",type=BarImpl2.class), 
     }) 
     Bar bar; 
    } 

    @XmlTransient 
    public static abstract class Bar { 
     @XmlElement(name="baz") 
     String baz; 
    } 

    @XmlRootElement(name="foo") 
    public static class FooImpl extends Foo { } 

    @XmlRootElement(name="bar") 
    public static class BarImpl extends Bar { } 

    public static class BarImpl2 extends Bar { } 
} 
+0

的一件事它缺少的是,如果我做BarImpl2,巴(中富)已經被標記爲BarImpl。 – 2012-03-06 17:29:49

+0

我已經更新了我的答案,使用'@ XmlElements'來處理這個用例。 – 2012-03-06 17:52:56

+0

它的工作!現在唯一的煩惱是BarImpl2的實現者需要更改Foo中的註釋,但這只是一個煩惱。 – 2012-03-07 07:45:58