I'm using jersey and jackson together to develop my REST API, and I'm having a problem when deserializing a date string. I have register a provider class in Jersey:
@Provider
public class MyJsonProvider extends JacksonJsonProvider {
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Override
public void 开发者_运维百科writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
ObjectMapper mapper = locateMapper(type, mediaType);
// Enable human readable date format
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
mapper.getDeserializationConfig().setDateFormat(sdf);
mapper.getSerializationConfig().setDateFormat(sdf);
// Enable JAXB annotation, with Jackson annotation being the preferred one.
AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new JaxbAnnotationIntrospector();
AnnotationIntrospector introspector = new AnnotationIntrospector.Pair(primary, secondary);
mapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
mapper.getSerializationConfig().setAnnotationIntrospector(introspector);
super.writeTo(value, type, genericType, annotations, mediaType, httpHeaders, entityStream);
}
}
And it seems like Jersey picked it up during start up:
Jan 24, 2011 2:53:23 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Provider classes found:
class com.mypackage.MyJsonProvider
And it works fine for serialization, but when I tried to deserialize a string like 2010-01-25 00:00:00
, I'm getting a mapping error:
SEVERE: Servlet.service() for servlet JerseyWebApplication threw exception
org.codehaus.jackson.map.JsonMappingException: Can not construct instance of java.util.Date from String value '2010-01-25 00:00:00': not a valid representation (error: Can not parse date "2010-01-25 00:00:00": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
at [Source: org.apache.catalina.connector.CoyoteInputStream@6a3d899a; line: 3, column: 37]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:159)
at org.codehaus.jackson.map.deser.StdDeserializationContext.weirdStringException(StdDeserializationContext.java:222)
at org.codehaus.jackson.map.deser.StdDeserializer._parseDate(StdDeserializer.java:283)
at org.codehaus.jackson.map.deser.DateDeserializer.deserialize(DateDeserializer.java:26)
at org.codehaus.jackson.map.deser.DateDeserializer.deserialize(DateDeserializer.java:17)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:135)
at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:221)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:391)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:286)
at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:1568)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:788)
at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:398)
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:454)
It seems like Jersey is still using JacksonJsonProvider
to handle the deserialization somehow. I'm not sure what I am doing wrong. How should I configure the jackson within jersey? Thanks!
super.writeTo method calls locateMapper(type, mediaType) again and creates a new instance of mapper object so the mapper object on which you configure the dateformat is never used. You can confirm in debug mode.
What you can do is create your own mapper object by creating a constructor
MyJsonProvider(){
ObjectMapper mapper = new ObjectMapper();
// Enable human readable date format
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
mapper.getDeserializationConfig().setDateFormat(sdf);
mapper.getSerializationConfig().setDateFormat(sdf);
// Enable JAXB annotation, with Jackson annotation being the preferred one.
AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new JaxbAnnotationIntrospector();
AnnotationIntrospector introspector = new AnnotationIntrospector.Pair(primary, secondary);
mapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
mapper.getSerializationConfig().setAnnotationIntrospector(introspector);
super(mapper);}
Then you dont need to override the writeTo method
精彩评论