Approach #1
Write custom serializer and deserializer
import java.io.IOException;
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;
/**
* Used to serialize Java.util.Date, which is not a common JSON
* type, so we have to create a custom serialize method;.
*
*/
public class JsonDateSerializer extends JsonSerializer<Date>{
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = DateAdapter.printDate(date);
gen.writeString(formattedDate);
}
}
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;
/**
* Used to serialize Java.util.Date, which is not a common JSON
* type, so we have to create a custom serialize method;.
*
*/
public class JsonDateSerializer extends JsonSerializer<Date>{
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = DateAdapter.printDate(date);
gen.writeString(formattedDate);
}
}
import java.io.IOException;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class JsonDateDeSerializer extends JsonDeserializer<Date>{
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
System.out.println("JSON deserialization for " + jp.getText());
return DateAdapter.parseDate(jp.getText());
}
}
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class JsonDateDeSerializer extends JsonDeserializer<Date>{
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
System.out.println("JSON deserialization for " + jp.getText());
return DateAdapter.parseDate(jp.getText());
}
}
Annotate each date field
Where ever date is declared, you annotate with following Jackson annotation specifying the serializer/deserializer to use
@JsonSerialize(using=JsonDateSerializer.class, as = Date.class)
public Date getCreatedOn() {
return createdOn;
}
/**
* Sets the value of the createdOn property.
*
* @param value
* allowed object is
* {@link String }
*
*/
@JsonDeserialize(using=JsonDateDeSerializer.class, as = Date.class)
public void setCreatedOn(Date value) {
this.createdOn = value;
}
public Date getCreatedOn() {
return createdOn;
}
/**
* Sets the value of the createdOn property.
*
* @param value
* allowed object is
* {@link String }
*
*/
@JsonDeserialize(using=JsonDateDeSerializer.class, as = Date.class)
public void setCreatedOn(Date value) {
this.createdOn = value;
}
Note:
If you have getter/setters, annotations should NOT be given in fields but in getter/setter. See this.
Approach #2
The problem with above approach is you have to annotate each and every field having type Date. Sometimes you won't have access to code or have just the effect to be applied globally for all Date types. If so, you can define a custom ContextResolver and have Jackson use it.
package com.samples.resolvers;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
@Provider
@Produces("application/json")
public class JacksonConfigurator implements ContextResolver<ObjectMapper> {
import javax.ws.rs.Produces;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
@Provider
@Produces("application/json")
public class JacksonConfigurator implements ContextResolver<ObjectMapper> {
public final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
private ObjectMapper mapper = new ObjectMapper();
public JacksonConfigurator() {
SerializationConfig serConfig = mapper.getSerializationConfig();
serConfig.setDateFormat(DATE_FORMAT);
DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
deserializationConfig.setDateFormat(DATE_FORMAT);
mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
}
@Override
public ObjectMapper getContext(Class<?> arg0) {
return mapper;
}
}
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
private ObjectMapper mapper = new ObjectMapper();
public JacksonConfigurator() {
SerializationConfig serConfig = mapper.getSerializationConfig();
serConfig.setDateFormat(DATE_FORMAT);
DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
deserializationConfig.setDateFormat(DATE_FORMAT);
mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
}
@Override
public ObjectMapper getContext(Class<?> arg0) {
return mapper;
}
}
and provide the package of this class for Jersey to scan and locate:
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.samples.resolvers;<other pkgs with resources etc.></param-value>
</init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.samples.resolvers;<other pkgs with resources etc.></param-value>
</init-param>
Its Life Saver !! Thanks a ton
ReplyDelete