2013-11-09 60 views
7

我已經返回該XML格式的服務:解組通用的清單與JAXB

<?xml version="1.0" encoding="UTF-8"?> 
<response> 
<status>success</status> 
<result> 
    <project> 
     <id>id1</id> 
      <owner>owner1</owner> 
    </project> 
    <project> 
     <id>id2</id> 
      <owner>owner2</owner> 
    </project> 
</result> 

<?xml version="1.0" encoding="UTF-8"?> 
<response> 
<status>success</status> 
<result> 
    <user> 
     <id>id1</id> 
     <name>name1</name> 
    </user> 
    <user> 
     <id>id2</id> 
      <name>name2</name> 
    </user> 
</result> 

我想用這些來解讀檢索XML課程:

結果

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Response<T> { 

    @XmlElement 
    protected String status; 

    @XmlElementWrapper(name = "result") 
    @XmlElement 
    protected List<T> result; 
} 

項目

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Project { 

    @XmlElement 
    public String id; 

    @XmlElement 
    public String owner; 
} 

用戶

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class User { 

    @XmlElement 
    public String id; 

    @XmlElement 
    public String name; 
} 

首先不工作的解決方案

JAXBContext context = JAXBContext.newInstance(Response.class, Project.class, User.class); 
Unmarshaller unmarshaller = context.createUnmarshaller(); 

StreamSource source = new StreamSource(new File("responseProject.xml")); 
Response<Project> responseProject = (Response<Project>)unmarshaller.unmarshal(source); 
System.out.println(responseProject.getStatus()); 
for (Project project:responseProject.getResult()) System.out.println(project); 

source = new StreamSource(new File("responseUser.xml")); 
Response<User> responseUser = (Response<User>)unmarshaller.unmarshal(source); 
System.out.println(responseUser.getStatus()); 
for (User user:responseUser.getResult()) System.out.println(user); 

我得到一個空的列表。

二沒有工作液

本文http://blog.bdoughan.com/2012/11/creating-generic-list-wrapper-in-jaxb.html靈感來自我已經修改了Response類:

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Response<T> { 

    @XmlElement 
    protected String status; 

    @XmlAnyElement(lax=true) 
    protected List<T> result; 
} 

然後用這個代碼測試它:

Response<Project> responseProject = unmarshal(unmarshaller, Project.class, "responseProject.xml"); 
    System.out.println(responseProject.getStatus()); 
    for (Project project:responseProject.getResult()) System.out.println(project); 

private static <T> Response<T> unmarshal(Unmarshaller unmarshaller, Class<T> clazz, String xmlLocation) throws JAXBException { 
    StreamSource xml = new StreamSource(xmlLocation); 
    @SuppressWarnings("unchecked") 
    Response<T> wrapper = (Response<T>) unmarshaller.unmarshal(xml, Response.class).getValue(); 
    return wrapper; 
} 

而且我得到這個異常讀取響應列表:

Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to org.test.Project 

注意:我無法修改原始XML。除Project和User外還有更多類型。

+2

的以下將幫助:http://blog.bdoughan.com/2012/11/creating-generic-list-wrapper-in-jaxb.html –

+0

嗨,布萊斯,我已經找到你的文章,很好順便說一句,但我得到嘗試讀取列表的異常:線程「main」中的異常java.lang.ClassCastException:com.sun.org.apache.xerces.internal.dom.ElementNSImpl無法轉換爲org.test.Project 我將更新問題與嘗試的解決方案。 – Fedy2

+0

您需要確保'JAXBContext'知道所有類,並且集合中的每個項目都用'@ XmlRootElement'註解。 –

回答

11

感謝Blaise Doughan和他的文章,我找到了解決方案。

首先,我們需要在文章中所提供的包裝類:

@XmlRootElement 
public class Wrapper<T> { 

    private List<T> items; 

    public Wrapper() { 
    items = new ArrayList<T>(); 
    } 

    public Wrapper(List<T> items) { 
    this.items = items; 
    } 

    @XmlAnyElement(lax=true) 
    public List<T> getItems() { 
    return items; 
    } 
} 

然後我修改了Response類,以使用它:

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Response<T> { 

    @XmlElement 
    protected String status; 

    @XmlElement 
    protected Wrapper<T> result; 

    ... 

    public Response(String status, List<T> result) { 
    this.status = status; 
    this.result = new Wrapper<>(result); 
    } 

    ... 

    public List<T> getResult() { 
    return result.getItems(); 
    } 

    ... 
} 

最後的解組代碼:

JAXBContext context = JAXBContext.newInstance(Response.class, Project.class, User.class, Wrapper.class); 
Unmarshaller unmarshaller = context.createUnmarshaller(); 

StreamSource source = new StreamSource(new File("responseProject.xml")); 
Response<Project> responseProject = (Response<Project>)unmarshaller.unmarshal(source); 
System.out.println(responseProject.getStatus()); 
for (Project project:responseProject.getResult()) System.out.println(project); 

source = new StreamSource(new File("responseUser.xml")); 
Response<User> responseUser = (Response<User>)unmarshaller.unmarshal(source); 
System.out.println(responseUser.getStatus()); 
for (User user:responseUser.getResult()) System.out.println(user); 

我已經將Wrapper類添加到上下文類列表中。

或者,也可以此註釋添加到響應類:

@XmlSeeAlso({Project.class, User.class}) 
1

響應類使用@XmlSeeAlso({Project.class,User.class})具有產生一些垃圾的缺點對列表中的每個實體的信息:的xmlns:的xsi = 「http://www.w3.org/2001/XMLSchema-instance」 的xsi:type = 「userAccount」

<resources> 
    <links> 
     <link> 
      <rel>self</rel> 
      <uri>http://localhost:8080/salonea-1.0/rest/user-accounts?offset=0&amp;limit=2</uri> 
     </link> 
     <link> 
      <rel>prev</rel> 
      <uri></uri> 
     </link> 
     <link> 
      <rel>next</rel> 
      <uri>http://localhost:8080/salonea-1.0/rest/user-accounts?offset=2&amp;limit=2</uri> 
     </link> 
    </links> 
    <collection> 
     <user-account 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="userAccount"> 
      <accountType>user</accountType> 
      <activationCode>638f502a0e409348ccc2e36c24907f0</activationCode> 
      <email>[email protected]</email> 
      <login>michzio</login> 
      <password>sAmPL3#e</password> 
      <registrationDate>2015-09-03T17:30:03+02:00</registrationDate> 
      <userId>1</userId> 
     </user-account> 
     <user-account 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="userAccount"> 
      <accountType>user</accountType> 
      <activationCode>334bc79d142a291894bd71881e38a719</activationCode> 
      <email>[email protected]</email> 
      <login>alicja</login> 
      <password>zAczka!00</password> 
      <registrationDate>2015-09-03T17:30:03+02:00</registrationDate> 
      <userId>2</userId> 
     </user-account> 
    </collection> 
</resources>