Java 使用JAXB解组时将空元素转换为null

Java 使用JAXB解组时将空元素转换为null,java,jaxb,Java,Jaxb,使用以下JAXB注释定义类: class Course { @XmlElement (name = "book") List<Book> requiredBooks = new ArrayList<Book>(); class Course { @XmlElement (name = "book") @XmlJavaTypeAdapter(BookListAdapter.class) List<Book> requiredBooks = new ArrayL

使用以下JAXB注释定义类:

class Course {
@XmlElement (name = "book")
List<Book> requiredBooks = new ArrayList<Book>();
class Course {
@XmlElement (name = "book")
@XmlJavaTypeAdapter(BookListAdapter.class)
List<Book> requiredBooks = new ArrayList<Book>();
课程{
@xmlement(name=“book”)
List requiredBooks=新建ArrayList();
在对包含以下内容的XML文档进行解组时

<course>
  ...
  <book/>
</course>

...
最后,我将一本书添加到列表中,其所有属性都设置为null。我不控制XML输入。如何防止添加这本空书?我尝试在set..()或add..()方法中拦截,但结果发现JAXB在处理集合时绕过了setter。有什么建议吗?

试试这个

class Course {
@XmlElement (name="book", required=false)
List<Book> requiredBooks = new ArrayList<Book>();
课程{
@XmlElement(name=“book”,必需=false)
List requiredBooks=新建ArrayList();
好吧,我找到了一种方法,尽管我觉得它不是非常优雅

编辑:实际上,下面的解决方案无法正常工作。它实际上不会将任何条目添加到列表中,无论它们是空元素还是完全由数据构成

也许我做错了,所以欢迎任何评论

我创建了一个适配器来处理转换,并使用注释通知JAXB:

class Course {
@XmlElement (name = "book")
List<Book> requiredBooks = new ArrayList<Book>();
class Course {
@XmlElement (name = "book")
@XmlJavaTypeAdapter(BookListAdapter.class)
List<Book> requiredBooks = new ArrayList<Book>();
课程{
@xmlement(name=“book”)
@XmlJavaTypeAdapter(BookListAdapter.class)
List requiredBooks=新建ArrayList();
然后定义了我的适配器:

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;
    }
}
静态类BookListAdapter扩展了XmlAdapter
{
公共书籍[]元帅(列表)
{
if(aBookList!=null)
{
返回aBookList.toArray(新书[aBookList.size()]);
}
返回null;
}
公共列表解组(Book[]aBookArray)
{
List bookList=newarraylist();
if(aBookArray!=null)
{
for(书籍:aBookArray)
{
if(StringUtils.isNotEmpty(book.getTitle())
{
图书目录。添加(图书);
}
}
}
归还书目;
}
}
它可以按我所希望的那样工作,但正如我前面所说的,我不相信它的优雅。
编辑:如上所述,这不起作用,但可能是由于我的某些错误。

这里有一个可行的解决方案。同样,优雅被抛在了后面

JAXB定义了两个回调:beforeUnmarshal和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();
                }
            }
        }
    }
  }
课程
{
@xmlement(name=“book”)
List requiredBooks=新建ArrayList();
...
解组后无效(解组器aUnmarshaller,对象aParent)
{
if(requiredBooks!=null)
{
迭代器迭代器=requiredBooks.Iterator();
while(iterator.hasNext())
{
Book Book=iterator.next();
if(StringUtils.isEmpty(book.getTitle()))
{
//没有书名的书被认为是无效的
iterator.remove();
}
}
}
}
}
虽然这是可行的,但它最大的问题是缺少用于实现afterUnmarshal的接口。JAXB使用反射来查找它,但我认为这会很方便(并且会减少调试/维护)如果JAXB只是提供接口和/或ABSTRACT实现。事实上,如果afterUnmarshal的签名在将来发生变化呢?这段代码将神秘地停止工作,就像它应该的那样。

在中,我们有一个空策略的概念。这个空策略为您提供了一些关于如何表示空的灵活性

您可以将类修改为如下所示:

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>();
}
import org.eclipse.persistence.oxm.annotations.xml表示;
导入org.eclipse.persistence.oxm.annotations.XmlNullPolicy;
@XmlRootElement
班级课程{
@xmlement(name=“book”)
@XmlNullPolicy(
nullRepresentationForXml=XmlMarshallNullRepresentation.EMPTY_节点,
emptynoderepresentsnall=true)
List requiredBooks=新建ArrayList();
}
这将通知MOXy JAXB,对于此属性,您希望将此属性的空元素视为null

对于此XML:

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

你好,世界
requiredBooks属性将解组为:null、aBook、null

目前有一个bug正在阻止我们正在解决的问题。您可以在此处跟踪此问题的进展:


    • 我也做了类似的尝试:

      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);
      }
      
      public List getPhotos(){
      removeUninitializedPhotos();
      归还照片;
      }
      private void removeUninitializedPhotos(){
      List photosToRemove=new ArrayList();
      (照片:照片){
      if(photo.getId()==null){
      photosToRemove.add(照片);
      }
      }
      photos.removeAll(PhotostoreRemove);
      }
      

      但我发现它太可怕了,以至于我最终切换到;)

      我遇到了类似的问题-我需要处理一个包含接口的ArrayList。我刚刚为接口创建了一个适配器(MyInterfaceAdapter)并对列表进行了注释:

      @XmlElementWrapper(name="myInterface")
      @XmlJavaTypeAdapter(value=MyInterfaceAdapter.class)
      List<MyInterface> list = new ArryList<MyInterface>;
      
      @xmlementwrapper(name=“myInterface”)
      @XmlJavaTypeAdapter(值=MyInterfaceAdapter.class)
      列表=新的ArryList;
      
      我的适配器如下所示:

      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 ... }
          }
      }
      
      公共类MyInterfaceAdapter扩展了XmlAdapter{
      @凌驾
      公用传感器解组器(MyType v)引发异常{
      返回(MyInterface)v;
      }
      @凌驾
      public AbstractSensor封送处理程序(MyInterface v)引发异常{
      if(v==null)//在空列表的情况下
      {
      返回null;
      }否则
      {….返回新的…}
      }
      }
      
      解组后,我得到了一个初始化的ArrayList(甚至是空的)


      我认为在上面所问的问题中,可以添加额外的条件,并在书籍为空的情况下返回null。另一方面,我也不喜欢返回null。

      嗨,谢谢,但它不起作用。我想