How to Serialize Java.util.Date with Jackson JSON Processor / Spring 3.0

September 17, 2010 | By | 13 Comments

Quick tip: how to serialize a java.util.Date object with Jackson JSON Processor – Sprinv MVC 3.

quick tips How to Serialize Java.util.Date with Jackson JSON Processor / Spring 3.0

Scenario:

I have the following Java Bean:

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;
}

And I have the following method in my controller:

public @ResponseBody Map<String,List<Company>> view() throws Exception

Which returns a list of Company.

The @ResponseBody annotation instructs Spring MVC to serialize the hashmap to the client. Spring MVC automatically serializes to JSON because the client accepts that content type:

{"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}

Take a look how the date attibute is being serialized: “date”:1188615600000. Jackson uses default strategy to determine date formatting in serialization.

One of the annotations Jackson has is @JsonSerialize. You basically use this annotation for configuring serialization aspects. In my case, I decorated by model objects date getter method with this annotation:

@JsonSerialize(using=JsonDateSerializer.class)
public Date getDate() {
	return date;
}

JsonDateSerializer is a class I wrote that extends JsonSerializer that will handle the serialization for this field:

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)
 * http://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);
	}

}

And this is how my object is being serialized now:

{"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}

Happy Coding! icon smile How to Serialize Java.util.Date with Jackson JSON Processor / Spring 3.0

Filed in: JSON | Tags: , , , , ,

Comments (13)

  1. Aggelos Karalias (mehiel)

    Or if your date format is global you could create a custom object mapper and avoid using @JsonSerialize every time.

    An example. Spring-enabled, implementation could be like that:

    @Component(“jacksonObjectMapper”)
    public class CustomObjectMapper extends org.codehaus.jackson.map.ObjectMapper {

    //constructors

    @PostConstruct
    public void afterPropertiesSet() throws Exception {
    getSerializationConfig().setDateFormat(new SimpleDateFormat(“yyyy-MM-dd’T'HH:mm:ss.SZ”)); //ISO 8601

    //usually here, I also enable JAXB annotations and disable auto-detection (for security reasons, whitelisting the properties I want serialized is better)
    }
    }

    And then you can you can configure your message converters with Jackson using something like:

    King Regards,
    Aggelos

  2. Aggelos Karalias (mehiel)

    Oops.. I thought xlm would be escaped on submit :-)

    So the message converter conf is like:

    <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
    <property name="objectMapper" ref="jacksonObjectMapper" />
    </bean>

  3. wow it’s awesome@!!
    very helpful me~
    thanks guys

  4. found your site on del.icio.us today and really liked it.. i bookmarked it and will be back to check it out some more later

  5. Colin

    Thanks for the serialization example. One thing to keep in mind is that SimpleDateFormat is not thread safe. If this code is running in a multithreaded context then it is not safe to share the SimpleDateFormat as a class static.

  6. Guido

    +1 to Colin comment, I was thinking just the same

  7. Good stuff! Love to see more articles showing ways to configure Jackson.
    One more way to do this with Jackson is to just ask Jackson to serialize dates using ISO-8601. This can be done via ObjectMapper:

    objectMapper.configure( SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);

    which will then print out textual date descriptions.There’s also a method to specify date format to use, if that matters; but usually above is enough.

  8. Andy Bowes

    Colin, you are correct that the SimpleDateFormat class is not thread-safe however Jackson’s StdDeserializationContext & StdSerializerProvider take care of this by creating a clone of the DateFormat instance for thread which parses or formats a date field.

  9. mg

    Hi Loiane,
    You article helped me a lot. Have you got working example of deserialization from json to Date field?

  10. Dave Schumann

    This is great, thanks! Do you have any idea how to get this annotation when using the “xjc” code generator?

Leave a Reply

Trackback URL | RSS Feed for This Entry