2010-11-15 22 views
9

解組類的定義與下列JAXB註釋時轉化空元件插入到空添加到列表中,並將其所有屬性設置爲空。我不控制XML輸入。我怎樣才能防止這本空書被添加?我嘗試攔截集..()或添加..()方法,但事實證明,JAXB在處理集合時繞過了setter。有什麼建議麼?與JAXB

回答

5

這裏有一個解決方案,確實工作。再次,優雅被拋在後面。

JAXB定義了兩個回調函數:beforeUnmarshal和afterUnmarshal。通過執行afterUnmarshal清理清單,我能夠達到預期的效果。

class Course 
    { 
    @XmlElement (name = "book") 
    List<Book> requiredBooks = new ArrayList<Book>(); 
    ... 
    void afterUnmarshal(Unmarshaller aUnmarshaller, Object aParent) 
    { 
     if (requiredBooks != null) 
     { 
      Iterator<Book> iterator = requiredBooks.iterator(); 
      while (iterator.hasNext()) 
      { 
       Book book = iterator.next(); 
       if (StringUtils.isEmpty(book.getTitle())) 
       { 
        // a book without title is considered invalid 
        iterator.remove(); 
       } 
      } 
     } 
    } 
    } 

雖然這可行,但最大的問題是沒有實現afterUnmarshal的接口。 JAXB使用反射查找它,但如果JAXB只是提供接口和/或absract實現,我認爲它會很方便(並且會減少調試/維護)。事實上,如果afterUnmarshal的簽名在將來發生變化呢?這段代碼會神祕地停止工作,因爲它應該是。

+0

我有這個相同的問題。糟糕的解決方案,但至少它工作。沒有機會找到更好的解決方法? – 2011-09-09 21:06:15

1

試試這個,

class Course { 
@XmlElement (name="book", required=false) 
List<Book> requiredBooks = new ArrayList<Book>(); 
+0

嗨。謝謝,但它沒有奏效。我想象這個指令告訴JAXB如果元素完全缺失,不要認爲它是一個錯誤,但它不會改變發生空標記時的行爲。 – torngat 2010-11-15 14:07:08

+0

@torngat:你用'nillable'試過'required'嗎?我實際上是盲目地猜測,因爲不能相信它沒有任何內置的解決方案來滿足這個非常基本的常規合理需求。 – 2010-11-15 17:55:49

+0

是的,我試過了,沒有結果。我的理解是,這些額外的指令主要用於編組(即生成)XML。然後編組人員會知道一個元素不是必需的,但是,如果它是空的,它將被包含像這樣: torngat 2010-11-16 17:20:15

2

好吧,我 發現做這件事,但我並不覺得超級優雅。

編輯:其實,下面的解決方案不正常工作。它實際上不會將條目添加到列表中,而不管它們是否爲空元素或完全由數據組成。

也許我做錯了,所以歡迎任何評論。

我創建了一個適配器來處理轉換和使用註釋通知JAXB:

class Course { 
@XmlElement (name = "book") 
@XmlJavaTypeAdapter(BookListAdapter.class) 
List<Book> requiredBooks = new ArrayList<Book>(); 

,然後確定我的適配器:

static class BookListAdapter extends XmlAdapter<Book[], List<Book>> 
{ 
    public Book[] marshal(List<Book> aBookList) 
    { 
     if (aBookList!= null) 
     { 
      return aBookList.toArray(new Book[aBookList.size()]); 
     } 
     return null; 
    } 

    public List<Book> unmarshal(Book[] aBookArray) 
    { 
     List<Book> bookList = new ArrayList<Book>(); 
     if (aBookArray != null) 
     { 
      for (Book book : aBookArray) 
      { 
       if (StringUtils.isNotEmpty(book.getTitle())) 
       { 
        bookList.add(book); 
       } 
      } 
     } 
     return bookList; 
    } 
} 

它的工作原理,因爲我也想,但是,正如我剛纔所說,我不相信它的優雅。
編輯:如上所述,這不起作用,但可能是由於我的一些錯誤。

4

EclipseLink JAXB (MOXy)我們有一個空策略的概念。這個空策略爲您提供了一些如何表示null的靈活性。

你可以修改你的類如下所示:

import org.eclipse.persistence.oxm.annotations.XmlMarshalNullRepresentation; 
import org.eclipse.persistence.oxm.annotations.XmlNullPolicy; 

@XmlRootElement 
class Course { 

    @XmlElement (name = "book") 
    @XmlNullPolicy(
     nullRepresentationForXml = XmlMarshalNullRepresentation.EMPTY_NODE, 
     emptyNodeRepresentsNull=true) 
    List<Book> requiredBooks = new ArrayList<Book>(); 
} 

此通知莫西JAXB,對於這個屬性,你希望把空元素爲空此屬性。

對於這個XML:

<course> 
    <book/> 
    <book> 
     <title>Hello World</title> 
    </book> 
    <book/> 
</course> 

requiredBooks屬性將作爲解組:空,ABOOK,空。

目前有一個錯誤,正在阻止我們現在正在處理的這個工作。您可以跟蹤在這個問題上這裏的進展:

+0

是的,我意識到MOXy的可能性(另一個線程討論它)。我只能希望它在默認情況下在JAXB中可用。看起來很奇怪,這樣的選擇被遺漏了。 – torngat 2010-11-17 16:43:47

1

我做了一個類似的cludge:

public List<Photo> getPhotos() { 
    removeUninitializedPhotos(); 
    return photos; 
} 

private void removeUninitializedPhotos() { 
    List<Photo> photosToRemove = new ArrayList<Photo>(); 
    for (Photo photo : photos) { 
     if (photo.getId() == null) { 
      photosToRemove.add(photo); 
     } 
    } 
    photos.removeAll(photosToRemove); 
} 

但是我發現這太可怕了,我剛剛結束了在切換到Gson ;)

0

我有類似的問題 - 我需要處理包含接口的ArrayList。我剛剛創建的接口(MyInterfaceAdapter)適配器和註釋的列表:

@XmlElementWrapper(name="myInterface") 
@XmlJavaTypeAdapter(value=MyInterfaceAdapter.class) 
List<MyInterface> list = new ArryList<MyInterface>; 

我的適配器是這樣的:

public class MyInterfaceAdapter extends XmlAdapter<MyType, MyInterface> { 

@Override 
public Sensor unmarshal(MyType v) throws Exception { 
    return (MyInterface) v; 
} 

@Override 
public AbstractSensor marshal(MyInterface v) throws Exception {  
     if(v == null) //In the case of empty list 
     { 
     return null; 
     } else 
     { .....return new ... } 
    } 
} 

解組我有一個初始化的ArrayList後(即使是空) 。

我認爲在上面提到的問題中,可以添加附加條件並在空白的情況下返回null。另一方面,我也不喜歡返回null。