programing tip

jaxb 비 정렬 화 타임 스탬프

itbloger 2020. 12. 4. 07:58
반응형

jaxb 비 정렬 화 타임 스탬프


Resteasy JAX-RS 서버 애플리케이션에서 타임 스탬프를 언 마샬링하기 위해 JAXB를 가져올 수 없습니다.

내 수업은 다음과 같습니다.

@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 HH : mm : ss"대신 "yyyy-MM-dd'T'HH : mm : ss"

해당 날짜 형식을 사용하려면 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);
    }

}

그런 다음 타임 스탬프 속성에이 어댑터를 지정합니다.

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이러한 목적으로 클래스를 도입 했지만 직접 사용하는 것은 매우 불편합니다.

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

If you want to keep the Date field, then you'll need to implement your own XmlAdapter class to tell JAXB to how turn your Date to and from XML.


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:

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

  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>

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

}

참고URL : https://stackoverflow.com/questions/2519432/jaxb-unmarshal-timestamp

반응형