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); } }