Java 使用JAXB解组时将空元素转换为null
使用以下JAXB注释定义类: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
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。嗨,谢谢,但它不起作用。我想