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:
[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
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
[/code]
E tenho outro objeto pra fazer o wraper do POJO acima:
[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
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;
}
}
[/code]
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:
[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
@RequestMapping(value="/company/view.action")
public @ResponseBody Companies view() throws Exception {}
[/code]
E quando fizermos uma chamada para o método do controller, vai retornar o seguinte XML para a view:
[code lang="xml" firstline="1" toolbar="true" collapse="false" wraplines="false" highlight="6,14"]
<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>
[/code]
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:
[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
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);
}
}
[/code]
E na classe POJO, é necessário simplesmente adicionar a annotation @XmlJavaTypeAdapter no método get da propriedade do tipo data.
[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false" highlight="23"]
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
}
[/code]
E se tentarmos chamar o método do controller novamente, vai retornar o seguinte XML:
[code lang="xml" firstline="1" toolbar="true" collapse="false" wraplines="false" highlight="6,14"]
<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>
[/code]
Problema resolvido!
Bons códigos! :)