JAXB Binding Customizado - Serializar Java.util.Date / Spring 3

07 Jun 2011
2 mins read

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