2013-06-26 40 views
2

我有一個RESTful Jersey Web服務,它將對象作爲XML返回。返回對象的成員之一是幾種可能的類型之一(全部來自公共基類),直到運行時才知道。我無法讓這個成員出現在輸出XML中,我將在下面展示。Java/Jersey/JAXB/MOXy - 給定基類對象的序列化派生成員

我已經減少了我的問題的一些示例類:

@XmlRootElement 
public abstract class Animal { 

    public String type; 

    public Animal() { 
     type = "?"; 
    } 

    public Animal(String type) { 
     this.type = type; 
    } 
} 

@XmlRootElement 
public class Mammal extends Animal { 

    public String name; 

    public Mammal() { 
     name = "?"; 
    } 

    public Mammal(String type, String name) { 
     super(type); 
     this.name = name; 
    } 
} 

@XmlRootElement 
public class Zoo { 
    private Animal creature; 

    @XmlElementRef 
    public Animal getCreature() { 
     return creature; 
    } 

    public void setCreature(Animal creature) { 
     this.creature = creature; 
    } 

    public Zoo() { 
     creature = new Mammal("Mouse", "Mickey"); 
    } 
} 

@Path("/test") 
public class TestResource { 

    @GET 
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
    public Zoo get() { 
     Zoo z = new Zoo(); 
     return z; 
    } 
} 

當我打電話,我得到以下響應服務:

<zoo/> 

不包括預期的生物。

如果我改變從動物(抽象基類)的成員「生物」的哺乳動物(派生類)的類型然後我得到預期的輸出,但是這不是一個合適的解決方案。

所以我下面的代碼添加到get()方法:

// DIAGNOSTIC CODE: Convert object to XML and send to System.out 
    try { 
     JAXBContext context = JAXBContext.newInstance(Zoo.class, Mammal.class); 
     Marshaller m = context.createMarshaller(); 
     m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     m.marshal(z, System.out); 
    } catch (JAXBException ex) { 
     ex.printStackTrace(); 
    } 

,現在即使從服務的XML是錯誤的(只是空標籤)我在控制檯看到正確的輸出:現在

<?xml version="1.0" encoding="UTF-8"?> 
<zoo> 
    <mammal> 
     <type>Mouse</type> 
     <name>Mickey</name> 
    </mammal> 
</zoo> 

,爲了得到該輸出,我必須確保Mammal.class傳遞給JAXBContext.newInstance(),否則我得到了在輸出相同的空標籤,所以我猜問題在於由Web服務完成的XML序列化不知道派生的哺乳動物類,因此無法正確序列化對象。這是一個正確的診斷?我如何解決它?

回答

2

問題是澤西島將從返回類型Zoo創建的默認JAXBContext不會意識到Mammal類。它將拉入Animal,但不包括其任何子類(因爲API不存在這樣做)。這就是爲什麼當你創建一個JAXBContext,爲了記錄的目的而知道Mammal一切正常。

解決方案#1 - 利用@XmlSeeAlso

@XmlSeeAlso註解告訴JAXB IMPL,當你處理此類還處理這些其他類。通常用於引用映射的子類。

@XmlRootElement 
@XmlSeeAlso({Mammal.class}) 
public abstract class Animal { 

    public String type; 

    public Animal() { 
     type = "?"; 
    } 

    public Animal(String type) { 
     this.type = type; 
    } 
} 

解決方案2 - 利用一個JAX-RS ContextResolver

我提到的問題是由於默認JAXBContext澤西創建將不會意識到Mammal類的。您可以使用ContextResolver返回JAXBContext即。下面是創建的實例的鏈接ContextResolver

相關問題