60 votes

horodatage jaxb unmarshal

Je ne parviens pas à obtenir un horodatage de JAXB dans une application serveur Resteasy JAX-RS.

Ma classe ressemble à ceci:

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

Des idées?

Merci.

108voto

Blaise Doughan Points 75613

JAXB peut gérer la classe java.util.Date. Cependant il attend le format:

"aaaa-MM-jj'T'HH: mm: ss" au lieu de "aaaa-MM-jj HH: mm: ss"

Si vous voulez utiliser ce format de date, je suggérerais d'utiliser un XmlAdapter, il ressemblerait à ceci:

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

}
 

Vous devez ensuite spécifier cet adaptateur sur votre propriété 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; 
    } 

}
 

11voto

skaffman Points 197885

JAXB ne peut maréchal Date objets directement, parce qu'ils n'ont pas suffisamment d'informations pour être sans équivoque. JAXB introduit l' XmlGregorianCalendar de la classe dans ce but, mais c'est très désagréable à utiliser directement.

Je Suggère de changer votre timestamp champ XmlGregorianCalendar, et de changer votre divers méthodes pour mettre à jour ce champ, tout en conservant l'interface publique que vous avez déjà, lorsque cela est possible.

Si vous voulez garder l' Date domaine, alors vous aurez besoin de mettre en place votre propre XmlAdapter classe de dire JAXB pour comment transformer votre Date à et à partir de XML.

3voto

Andrea Luciano Points 91

Pour que le marshaller XML génère un xsd: date au format AAAA-MM-JJ sans définir un XmlAdapter, j'ai utilisé cette méthode pour créer une instance de 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));
}
 

Avec le résultat, j'ai initialisé le champ XMLGregorianCalendar de la classe générée par le compilateur JAXB (dans 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);
 

Et obtenu la balise formatée comme prévu:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X