2016-03-22 16 views
9

Sto costruendo una serie di classi collegate le cui istanze voglio essere in grado di eseguire il marshalling in XML, così posso salvarle in un file e leggerle di nuovo in seguito.Marshalling LocalDate con JAXB

Attualmente sto usando il seguente codice come un banco di prova:

import javax.xml.bind.annotation.*; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 

import java.time.LocalDate; 

public class LocalDateExample 
{ 
    @XmlRootElement 
    private static class WrapperTest { 
    public LocalDate startDate; 
    } 

    public static void main(String[] args) throws JAXBException 
    { 
    WrapperTest wt = new WrapperTest(); 
    LocalDate ld = LocalDate.of(2016, 3, 1); 
    wt.startDate = ld; 
    marshall(wt); 
    } 

    public static void marshall(Object jaxbObject) throws JAXBException 
    { 
    JAXBContext context = JAXBContext.newInstance(jaxbObject.getClass()); 
    Marshaller marshaller = context.createMarshaller(); 
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
    marshaller.marshal(jaxbObject, System.out); 
    } 
} 

L'output XML è:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<wrapperTest> 
    <startDate/> 
</wrapperTest> 

C'è un motivo per cui l'elemento startDate è vuota? Mi piacerebbe che contenga la rappresentazione in formato stringa della data (ad esempio toString()). Devo scrivere un codice mio per poterlo fare?

L'uscita del java -version è:

openjdk version "1.8.0_66-internal" 
OpenJDK Runtime Environment (build 1.8.0_66-internal-b17) 
OpenJDK 64-Bit Server VM (build 25.66-b17, mixed mode) 

risposta

13

si dovrà creare un XmlAdapter come questo:

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> { 
    public LocalDate unmarshal(String v) throws Exception { 
     return LocalDate.parse(v); 
    } 

    public String marshal(LocalDate v) throws Exception { 
     return v.toString(); 
    } 
} 

E annotare il campo utilizzando

@XmlJavaTypeAdapter(value = LocalDateAdapter.class) 

Vedi anche javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters se vuoi definire i tuoi adattatori a livello di pacchetto.

+0

sembra fare esattamente quello che voglio - grazie! – pwaring

2

http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html descrive l'impostazione del foro.

Joda-Time fornisce un'alternativa alle classi Date e Calendar attualmente fornite in Java SE. Poiché sono forniti in una libreria separata, JAXB non fornisce un mapping predefinito per queste classi.

Per registrare l'adattatore per tutti i file in un pacchetto. puoi aggiungere package-info.java nel pacchetto che vuoi registrare.

@XmlJavaTypeAdapters({ 
    @XmlJavaTypeAdapter(type=LocalDate.class, 
     value=LocalDateAdapter.class), 
}) 
package PACKAGE_NAME; 

import java.time.LocalDate; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; 

L'adattatore si presenta come:

import javax.xml.bind.annotation.adapters.XmlAdapter; 
import java.time.LocalDate; 

public class LocalDateAdapter extends XmlAdapter<String, LocalDate>{ 

    public LocalDate unmarshal(String v) throws Exception { 
     return LocalDate.parse(v); 
    } 

    public String marshal(LocalDate v) throws Exception { 
     return v.toString(); 
    } 

} 
+0

Non sto usando Joda Time, sto usando le classi 'java.time. *' (Che sembrano simili ma fanno parte di Java 8 e quindi non hanno bisogno di essere specificate come dipendenza). – pwaring

+0

Hai ragione. Stavo solo usando una mia vecchia soluzione per testare la tua. Aggiornerò la mia risposta –

+0

Grazie, l'altra risposta è stata un po 'più concisa, quindi l'ho contrassegnata come accettata. – pwaring

Problemi correlati