Como Serializar Java.util.Date com Jackson JSON Processor / Spring 3.0

20 Sep 2010
2 mins read

Dica rápida: como serializar um objeto java.util.Date com Jackson JSON Processor - Sprinv MVC 3.

Cenário:

Tenho o seguinte Java Bean:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.model;

import java.util.Date;

import org.codehaus.jackson.annotate.JsonAutoDetect;

@JsonAutoDetect
@Entity
public class Company {

private int id;
private double price;
private String company;
private Date date;
private String size;
private byte visible;
}
[/code]

E também tenho o seguinte método no meu Controller:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
public @ResponseBody Map<String,List<Company>> view() throws Exception
[/code]

Que retorna uma lista de Company.

A anotação @ResponseBody dá a instrução para o Spring MVC serializar o hashmap para o cliente (neste caso o browser). O Spring MVC automaticamente serializar o objeto para JSON por que o cliente aceita esse tipo de conteúdo (content type):

[code lang="js" firstline="1" toolbar="true" collapse="false" wraplines="false"]
{"total":27,"data":[{"price":71.72,"company":"3m Co","visible":1,"id":1,"size":"large","date":1188615600000},{"price":29.01,"company":"Aloca
Inc","visible":0,"id":2,"size":"medium","date":1185937200000},{"price":83.81,"company":"Altria Group
Inc","visible":0,"id":3,"size":"large","date":1186110000000},{"price":52.55,"company":"American Express Company","visible":1,"id":4,"size":"extra
large","date":1199412000000},{"price":64.13,"company":"American International Group
Inc.","visible":1,"id":5,"size":"small","date":1204599600000},{"price":31.61,"company":"AT&T Inc.","visible":0,"id":6,"size":"extra
large","date":1201831200000},{"price":75.43,"company":"Boeing Co.","visible":1,"id":7,"size":"large","date":1199152800000},{"price":67.27,"company":"Caterpillar
Inc.","visible":1,"id":8,"size":"medium","date":1196647200000},{"price":49.37,"company":"Citigroup,
Inc.","visible":1,"id":9,"size":"large","date":1195869600000},{"price":40.48,"company":"E.I. du Pont de Nemours and Company","visible":0,"id":10,"size":"extra
large","date":1178679600000}],"success":true}
[/code]

Dê uma olhada no atributo date/data que foi serializado: "date":1188615600000. Jackson usa a estratégia padrão para determinar o tipo de serialização. Lembrando que Data não é um tipo "primitivo" do JSON.

Uma anotação que encontrará no Jackson é @JsonSerialize. Você usa essa anotação para dizer quais são os aspectos da serialização. No meu caso, usei o método get do meu objeto:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
@JsonSerialize(using=JsonDateSerializer.class)
public Date getDate() {
return date;
}
[/code]

JsonDateSerializer é uma classe que criei que extende JsonSerializer que irá fazer a serialização do objeto do jeito que especificar. Neste caso, apenas pedi para formatar a data no formato mês-dia-ano:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.util;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
import org.springframework.stereotype.Component;

/**
* Used to serialize Java.util.Date, which is not a common JSON
* type, so we have to create a custom serialize method;.
*
* @author Loiane Groner
* http://loianegroner.com (English)
* https://loiane.com (Portuguese)
*/
@Component
public class JsonDateSerializer extends JsonSerializer<Date>{

private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");

@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {

String formattedDate = dateFormat.format(date);

gen.writeString(formattedDate);
}

}
[/code]

Dê uma olhada como o meu objeto data agora é serializado:

[code lang="js" firstline="1" toolbar="true" collapse="false" wraplines="false"]
{"total":27,"data":[{"price":71.72,"company":"3m Co","visible":1,"id":1,"size":"large","date":"09-01-2007"},{"price":29.01,"company":"Aloca
Inc","visible":0,"id":2,"size":"medium","date":"08-01-2007"},{"price":83.81,"company":"Altria Group
Inc","visible":0,"id":3,"size":"large","date":"08-03-2007"},{"price":52.55,"company":"American Express Company","visible":1,"id":4,"size":"extra
large","date":"01-04-2008"},{"price":64.13,"company":"American International Group
Inc.","visible":1,"id":5,"size":"small","date":"03-04-2008"},{"price":31.61,"company":"AT&T Inc.","visible":0,"id":6,"size":"extra
large","date":"02-01-2008"},{"price":75.43,"company":"Boeing Co.","visible":1,"id":7,"size":"large","date":"01-01-2008"},{"price":67.27,"company":"Caterpillar
Inc.","visible":1,"id":8,"size":"medium","date":"12-03-2007"},{"price":49.37,"company":"Citigroup,
Inc.","visible":1,"id":9,"size":"large","date":"11-24-2007"},{"price":40.48,"company":"E.I. du Pont de Nemours and Company","visible":0,"id":10,"size":"extra
large","date":"05-09-2007"}],"success":true}
[/code]

Problema resolvido!

Bons códigos! :)