JAXB Binding Customizado – Serializar Java.util.Date / Spring 3
JaxB consegue fazer a serialização de um objeto do tipo Java.util.Date por padrão, mas espera que a data esteja no seguinte formato: ”yyyy-MM-ddTHH:mm:ss“. E se precisar mudar esse formato? Como fazer?
Tive o mesmo problema quando estava trabalhando com Spring MVC 3 e precisava serializar uma data em JSON usando Jackson, e recentemente tive o mesmo problema trabalhando com Spring MVC 3 e serialização de XML com JaxB.
Vamos então ao problema! Show me the code!
Problema:
Tenho o seguinte POJO em Java que preciso serializar no formato XML usando Spring MVC 3:
package com.loiane.model;
import java.util.Date;
public class Company {
private int id;
private String company;
private double price;
private double change;
private double pctChange;
private Date lastChange;
//getters and setters
E tenho outro objeto pra fazer o wraper do POJO acima:
package com.loiane.model;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="companies")
public class Companies {
@XmlElement(required = true)
private List<Company> list;
public void setList(List<Company> list) {
this.list = list;
}
}
No controller do Spring, vou retornar uma List de Company através da annotation @ResponseBody – que vai fazer o parser do XML automaticamente com JaxB:
@RequestMapping(value="/company/view.action")
public @ResponseBody Companies view() throws Exception {}
E quando fizermos uma chamada para o método do controller, vai retornar o seguinte XML para a view:
<companies> <list> <change>0.02</change> <company>3m Co</company> <id>1</id> <lastChange>2011-09-01T00:00:00-03:00</lastChange> <pctChange>0.03</pctChange> <price>71.72</price> </list> <list> <change>0.42</change> <company>Alcoa Inc</company> <id>2</id> <lastChange>2011-09-01T00:00:00-03:00</lastChange> <pctChange>1.47</pctChange> <price>29.01</price> </list> </companies>
Note o formato da data. Não é o formato que preciso que retorne. Preciso que serialize no seguinte formato: “MM-dd-yyyy“
Solução:
É preciso criar uma classe que extends a classe XmlAdapter e fazer o override dos métodos marshal e unmarshal e adicionar a implementação para formatar a data do jeito que é necessário:
package com.loiane.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxbDateSerializer extends XmlAdapter<String, Date>{
private SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
@Override
public String marshal(Date date) throws Exception {
return dateFormat.format(date);
}
@Override
public Date unmarshal(String date) throws Exception {
return dateFormat.parse(date);
}
}
E na classe POJO, é necessário simplesmente adicionar a annotation @XmlJavaTypeAdapter no método get da propriedade do tipo data.
package com.loiane.model;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.loiane.util.JaxbDateSerializer;
public class Company {
private int id;
private String company;
private double price;
private double change;
private double pctChange;
private Date lastChange;
@XmlJavaTypeAdapter(JaxbDateSerializer.class)
public Date getLastChange() {
return lastChange;
}
//getters and setters
}
E se tentarmos chamar o método do controller novamente, vai retornar o seguinte XML:
<companies> <list> <change>0.02</change> <company>3m Co</company> <id>1</id> <lastChange>09-01-2011</lastChange> <pctChange>0.03</pctChange> <price>71.72</price> </list> <list> <change>0.42</change> <company>Alcoa Inc</company> <id>2</id> <lastChange>09-01-2011</lastChange> <pctChange>1.47</pctChange> <price>29.01</price> </list> </companies>
Problema resolvido!
Bons códigos!











Existe a possibilidade de passar por parâmetro qual o formato de data desejado? Temos um framework que utiliza o formato dd/mm/yyyy na classe JaxbDateSerializer, porém, um dos projetos precisa utilizar o formato yyyy-mm-dd.
Você sabe se é possível tornar a classe JaxbDateSerializer flexível para formatos diferentes ou a saída seria mesmo fazer o override no projeto específico?
Obrigada!
Oi Taís, desconheço fazer um formato genérico.
A saída seria override para cada formato mesmo.
Aeee Loiane tive este mesmo problema esta semana estava entre ir de long ou escrever um adapter do lado do android. Mas este post é a solução para a outra metade do problema!
Valeu pela dica!
Apesar de bem antigo, salvou minha pobre vida. rsrs
Valeu