2011-01-24 5 views
7

J'utilise conjointement jersey et jackson pour développer mon API REST, et j'ai un problème lors de la désérialisation d'une chaîne de date. J'ai enregistrer une classe de fournisseur à Jersey:Échec de désérialisation Jersey + Jackson avec l'objet date

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

Et il semble que Jersey a ramassé lors du démarrage:

Jan 24, 2011 2:53:23 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses 
INFO: Provider classes found: 
    class com.mypackage.MyJsonProvider 

Et cela fonctionne très bien pour la sérialisation, mais quand j'ai essayé de désérialiser une chaîne comme 2010-01-25 00:00:00, je reçois une erreur de cartographie:

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: [email protected]; 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) 

Il semble que Jersey utilise encore JacksonJsonProvider pour gérer la désérialisation en quelque sorte. Je ne suis pas sûr de ce que je fais mal. Comment dois-je configurer le jackson au sein du maillot? Merci!

+7

j'ai tout compris moi-même. Il s'avère que j'ai besoin de configurer la déserialization config dans la méthode readFrom(), pas la méthode writeTo(). Duh. – fei

+3

Pourquoi est-ce fermé comme "trop ​​localisé"? Jersey avec Jackson est un scénario commun. – Paul

+5

@fei vous pourriez l'ajouter comme une réponse – eis

Répondre

2

La méthode super.writeTo appelle à nouveau locateMapper (type, mediaType) et crée une nouvelle instance de l'objet mapper afin que l'objet mapper sur lequel vous configurez la dateformat ne soit jamais utilisé. Vous pouvez confirmer en mode débogage.

Ce que vous pouvez faire est de créer votre propre objet mappeur en créant un constructeur

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

Ensuite, vous ne avez pas besoin de passer outre la méthode WriteTo

Questions connexes