为什么JAXB需要一个无参数构造器来进行编组?
如果您尝试编组引用不具有无参数构造函数的复杂types的类,例如:
import java.sql.Date; @XmlRootElement(name = "Foo") @XmlAccessorType(XmlAccessType.FIELD) public class Foo { int i; Date d; //java.sql.Date does not have a no-arg constructor }
与Java的一部分JAXB实现,如下所示:
Foo foo = new Foo(); JAXBContext jc = JAXBContext.newInstance(Foo.class); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Marshaller marshaller = jc.createMarshaller(); marshaller.marshal(foo, baos);
JAXB将抛出一个
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions java.sql.Date does not have a no-arg default constructor
现在,我明白了为什么JAXB需要解组的无参构造函数 – 因为它需要实例化对象。 但为什么JAXB在编组时需要一个无参的构造函数呢?
此外,另一个尼特,为什么Java的JAXB实现会抛出一个exception,如果该字段为空,并且不打算编组?
我是否错过了某些东西,或者这些在Java的JAXB实现中只是错误的实现select?
当JAXB(JSR-222)实现初始化其元数据时,它确保它可以同时支持编组和解组。
对于没有无参数构造函数的POJO类,可以使用types级别的XmlAdapter
来处理它:
java.sql.Date
默认不支持(尽pipe在EclipseLink JAXB(MOXy)中是这样的)。 这也可以使用在字段,属性或包级别通过XmlAdapter
指定的XmlAdapter
进行处理:
- http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html
- http://blog.bdoughan.com/2011/01/jaxb-and-datetime-properties.html
此外,另一个尼特,为什么Java的JAXB实现会抛出一个exception,如果该字段为空,并且不打算编组?
你看到什么exception? 通常情况下,当一个字段为空时,它不包含在XML结果中,除非用@XmlElement(nillable=true)
注释,在这种情况下,元素将包含xsi:nil="true"
。
UPDATE
你可以做到以下几点:
SqlDateAdapter
下面是一个XmlAdapter
,它将从您的JAXB实现不知道如何处理的java.sql.Date
转换为XmlAdapter
执行的java.util.Date
:
package forum9268074; import javax.xml.bind.annotation.adapters.*; public class SqlDateAdapter extends XmlAdapter<java.util.Date, java.sql.Date> { @Override public java.util.Date marshal(java.sql.Date sqlDate) throws Exception { if(null == sqlDate) { return null; } return new java.util.Date(sqlDate.getTime()); } @Override public java.sql.Date unmarshal(java.util.Date utilDate) throws Exception { if(null == utilDate) { return null; } return new java.sql.Date(utilDate.getTime()); } }
富
XmlAdapter
是通过@XmlJavaTypeAdapter
注解注册的:
package forum9268074; import java.sql.Date; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement(name = "Foo") @XmlAccessorType(XmlAccessType.FIELD) public class Foo { int i; @XmlJavaTypeAdapter(SqlDateAdapter.class) Date d; //java.sql.Date does not have a no-arg constructor }
您似乎觉得JAXB自检代码将具有用于初始化的特定操作path。 如果是这样,那将导致很多重复的代码,并且会是一个糟糕的实现。 我会想象,JAXB代码有一个共同的例程,第一次检查一个模型类是需要的,并validation它遵循所有必要的约定。 在这种情况下,它是失败的,因为其中一个成员没有所需的无参数构造函数。 初始化逻辑很可能不是特定的编组/parsing器,也不太可能将当前的对象实例考虑在内。
一些企业和dependency injection框架使用reflectionClass.newInstance()来创build类的新实例。 这个方法需要一个公共的无参数构造函数来实例化对象。