基础问题
空的String
不是xsd:date
类型的有效值。为了符合XML模式,可选元素应该表示为不存在的节点。
为什么基础问题会影响您
所有JAXB实现都将识别空的String
不是xsd:date
的有效值。它们通过向ValidationEventHandler
实例报告来实现这一点。您可以通过执行以下操作自行查看:
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
@Override
public boolean handleEvent(ValidationEvent event) {
System.out.println(event);
return true;
}
});
您正在使用的 JAX-WS 实现利用
EclipseLink MOXy 作为 JAXB 提供程序。在您使用的版本中,MOXy 将默认抛出异常,当遇到严重性为 ERROR 的 ValidationEvent 时,而不是像参考实现那样是 FATAL_ERROR。这已经在以下错误中得到了修正:
解决方法
如果您正在直接使用JAXB API,可以简单地覆盖默认的ValidationEventHandler
。在JAX-WS环境中,可以使用XmlAdapter
提供自定义转换逻辑。我们将利用一个XmlAdapter
来覆盖如何处理对/从Date
的转换。
XmlAdapter(DateAdapter)
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateAdapter extends XmlAdapter<String, Date>{
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date unmarshal(String v) throws Exception {
if(v.length() == 0) {
return null;
}
return dateFormat.parse(v);
}
@Override
public String marshal(Date v) throws Exception {
if(null == v) {
return null;
}
return dateFormat.format(v);
}
}
Java模型(根)
使用@XmlJavaTypeAdapter
注解来引用XmlAdapter
。如果您希望这个XmlAdapter
适用于所有的Date
实例,您可以在包级别上注册它(请参见:http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html)。
import java.util.Date;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlSchemaType(name = "date")
@XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
private Date abc;
@XmlSchemaType(name="date")
@XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
private Date qwe;
}
演示代码
以下是一个独立的示例,您可以运行以查看所有内容是否正常工作。
jaxb.properties
要在独立示例中使用MOXy作为您的JAXB提供程序,您需要在与域模型相同的包中包含一个名为
jaxb.propeties
的文件,并具有以下条目(请参见:
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)。
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<abc></abc>
<qwe>2013-09-05</qwe>
</root>
演示
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18617998/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
输出
请注意,在编组的XML中,空的Date
字段被编组为缺失元素(参见:http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html)。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<qwe>2013-09-05</qwe>
</root>