jaxb unmarshal时间戳

我无法让JAXB在Resteasy JAX-RS服务器应用程序中解组时间戳。

我的课堂看起来像这样:

@XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "foo") public final class Foo { // Other fields omitted @XmlElement(name = "timestamp", required = true) protected Date timestamp; public Foo() {} public Date getTimestamp() { return timestamp; } public String getTimestampAsString() { return (timestamp != null) ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp) : null; } public void setTimestamp(final Date timestamp) { this.timestamp = timestamp; } public void setTimestamp(final String timestampAsString) { try { this.timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timestampAsString); } catch (ParseException ex) { this.timestamp = null; } } } 

有任何想法吗?

谢谢。

JAXB可以处理java.util.Date类。 不过,它预计的格式是:

“yyyy-MM-dd'T'HH:mm:ss”而不是“yyyy-MM-dd HH:mm:ss”

如果你想使用date格式,我会build议使用XmlAdapter,它看起来像下面这样:

 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 HH:mm:ss"); @Override public String marshal(Date v) throws Exception { return dateFormat.format(v); } @Override public Date unmarshal(String v) throws Exception { return dateFormat.parse(v); } } 

然后你可以在你的timestamp属性中指定这个适配器:

 import java.util.Date; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "foo") public final class Foo { // Other fields omitted @XmlElement(name = "timestamp", required = true) @XmlJavaTypeAdapter(DateAdapter.class) protected Date timestamp; public Foo() {} public Date getTimestamp() { return timestamp; } public void setTimestamp(final Date timestamp) { this.timestamp = timestamp; } } 

JAXB不能直接封送Date对象,因为它们没有足够的信息来确定。 JAXB为此目的引入了XmlGregorianCalendar类,但直接使用它是非常不愉快的。

我build议将您的timestamp字段更改为XmlGregorianCalendar ,并在可能的XmlGregorianCalendar更改您的各种方法来更新此字段,同时保留已有的公共接口。

如果您想保留Date字段,那么您需要实现自己的XmlAdapter类,以告诉JAXB如何将Date与XML XmlAdapter

为了让XML marshaller生成格式为YYYY-MM-DD的xsd:date,而不定义XmlAdapter,我使用这个方法来构build一个javax.xml.datatype.XMLGregorianCalendar的实例:

 public XMLGregorianCalendar buildXmlDate(Date date) throws DatatypeConfigurationException { return date==null ? null : DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd").format(date)); } 

结果我初始化了由JAXB编译器生成的类的XMLGregorianCalendar字段(在Eclipse中):

  Date now = new Date(); ... report.setMYDATE(buildXmlDateTime(now)); ... JAXBContext context = JAXBContext.newInstance(ReportType.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(new ObjectFactory().createREPORT(report), writer); 

并按预期格式获得标签:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <REPORT> ... <MY_DATE>2014-04-30</MY_DATE> ... </REPORT> 

使用这个适配器应该是线程安全的:

 public class DateXmlAdapter extends XmlAdapter<String, Date> { /** * Thread safe {@link DateFormat}. */ private static final ThreadLocal<DateFormat> DATE_FORMAT_TL = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); } }; @Override public Date unmarshal(String v) throws Exception { return DATE_FORMAT_TL.get().parse(v); } @Override public String marshal(Date v) throws Exception { return DATE_FORMAT_TL.get().format(v); } }