问题描述
如果您尝试编组一个引用了没有无参数构造函数的复杂类型的类,例如:
If you try to marshal a class which references a complex type that does not have a no-arg constructor, such as:
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 实现,如下所示:
with the JAXB implementation that is part of Java, as follows:
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 在编组时需要一个无参数的构造函数呢?
Now, I understand why JAXB needs a no-arg constructor on unmarshalling - because it needs to instantiate the object. But why does JAXB need a no-arg constructor while marshalling?
另外,另一个**,如果字段为空,为什么 Java 的 JAXB 实现会抛出异常,并且无论如何都不会被编组?
Also, another nit, why does Java's JAXB implementation throw an exception if the field is null, and isn't going to be marshalled anyway?
我是否遗漏了什么,或者这些只是 Java 的 JAXB 实现中的错误实现选择?
Am I missing something or are these just bad implementation choices in Java's JAXB implementation?
推荐答案
当一个 JAXB (JSR-222) 实现初始化其元数据,以确保它可以支持编组和解组.
When a JAXB (JSR-222) implementation initializes its metadata it ensures that it can support both marshalling and unmarshalling.
对于没有无参数构造函数的 POJO 类,您可以使用类型级别的 XmlAdapter 来处理它:
For POJO classes that do not have a no-arg constructor you can use a type level XmlAdapter to handle it:
- http://blog.bdoughan.com/2010/12/jaxb-and-immutable-objects.html
java.sql.Date 默认不支持(尽管在 EclipseLink JAXB(MOXy) 确实如此).这也可以使用通过 @XmlJavaTypeAdapter 在字段、属性或包级别指定的 XmlAdapter 来处理:
java.sql.Date is not supported by default (although in EclipseLink JAXB (MOXy) it is). This can also be handled using an XmlAdapter specified via @XmlJavaTypeAdapter at field, property, or package level:
- 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 实现会抛出一个如果该字段为空并且不会被编组,则异常还是?
Also, another nit, why does Java's JAXB implementation throw an exception if the field is null, and isn't going to be marshalled anyway?
您看到了什么异常?通常,当字段为 null 时,它不会包含在 XML 结果中,除非它使用 @XmlElement(nillable=true) 进行注释,在这种情况下,元素将包含 xsi:nil="true"代码>.
What exception are you seeing? Normally when a field is null it is not included in the XML result, unless it is annotated with @XmlElement(nillable=true) in which case the element will include xsi:nil="true".
更新
您可以执行以下操作:
SqlDateAdapter
下面是一个 XmlAdapter,它将从您的 JAXB 实现不知道如何处理的 java.sql.Date 转换为 java.util.Date 它的作用:
Below is an XmlAdapter that will convert from the java.sql.Date that your JAXB implementation doesn't know how to handle to a java.util.Date which it does:
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()); } }
Foo
XmlAdapter 是通过 @XmlJavaTypeAdapter 注解注册的:
The XmlAdapter is registered via the @XmlJavaTypeAdapter annotation:
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 }