Java jaxb 解组时间戳

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2519432/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:44:28  来源:igfitidea点击:

jaxb unmarshal timestamp

javadatetimejaxb

提问by Ralph

I cannot get JAXB to unmarshal a timestamp in a Resteasy JAX-RS server application.

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

My class looks like this:

我的课是这样的:

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

Any ideas?

有任何想法吗?

Thanks.

谢谢。

采纳答案by bdoughan

JAXB can handle the java.util.Date class. However it expects the format:

JAXB 可以处理 java.util.Date 类。但是它期望格式:

"yyyy-MM-dd'T'HH:mm:ss" instead of "yyyy-MM-dd HH:mm:ss"

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

If you want to use that date format I would suggest using an XmlAdapter, it would look something like the following:

如果您想使用该日期格式,我建议您使用 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);
    }

}

You would then specify this adapter on your timestamp property:

然后,您将在时间戳属性上指定此适配器:

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

}

回答by skaffman

JAXB cannot marshal Dateobjects directly, because they don't have enough information to be unambiguous. JAXB introduced the XmlGregorianCalendarclass for this purpose, but it's very unpleasant to use directly.

JAXB 不能Date直接编组对象,因为它们没有足够的信息来明确。JAXB 就是XmlGregorianCalendar为了这个目的引入了这个类,但是直接使用起来很不爽。

I Suggest changing your timestampfield to be a XmlGregorianCalendar, and change your various methods to update this field while retaining the public interface you already have, where possible.

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

If you want to keep the Datefield, then you'll need to implement your own XmlAdapterclass to tell JAXB to how turn your Dateto and from XML.

如果您想保留该Date字段,那么您需要实现自己的XmlAdapter类来告诉 JAXB 如何Date在 XML 和 XML 之间进行转换。

回答by Andrea Luciano

In order to get the XML marshaller to generate an xsd:date formatted as YYYY-MM-DD without defining an XmlAdapter I used this method to build an instance of javax.xml.datatype.XMLGregorianCalendar:

为了让 XML 编组器生成格式为 YYYY-MM-DD 的 xsd:date 而不定义 XmlAdapter 我使用这个方法来构建 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));
}

With the result I initialized the XMLGregorianCalendar field of the class generated by JAXB compiler (in Eclipse):

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

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

And obtained the tag formatted as expected:

并获得了按预期格式化的标签:

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

回答by dermoritz

Using this adapter should be thread safe:

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

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

}