(De)Serialize DateTime (Joda) with Jackson

大兔子大兔子 提交于 2019-12-24 10:53:41

问题


I am building a REST webservice. Some classes have an attribute of type DateTime (JodaTime).

When sending this object to my client (Javascript), my object

private DateTime date;

is transformed to

{ date: { chronology: {}, millis: 1487289600000 } }

The problem is that I have an error when sending this object back to the server because I cannot instantiate chronology

I would like to have something like { date: 1487289600000} - Any other format could work.

Environment

  • jackson-annotations 2.8.8
  • jackson-core 2.8.8
  • jackson-databin 2.8.8
  • jackson-datatype-joda 2.8.8
  • joda-time 2.7

My context resolver is

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {

    final ObjectMapper mapper = new ObjectMapper();

    public ObjectMapperContextResolver() {
        mapper.registerModule(new JodaModule());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }
}

What am I missing ? If I am not using ObjectMapperContextResolver I have the same result

Update following @Cássio Mazzochi Molin's answer

I added jackson-jaxrs-json-provider 2.8.8 , jackson-jaxrs-base 2.8.8 and jackson-module-jaxb-annotations 2.8.8

My context resolver is now like this

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {

    final ObjectMapper mapper = new ObjectMapper();

    public ObjectMapperContextResolver() {
        mapper.registerModule(new JodaModule());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }
}

And my application config

@javax.ws.rs.ApplicationPath("/")
public class ApplicationConfig extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        resources.add(AuthenticationFilter.class);
        resources.add(CORSFilter.class);
        resources.add(ObjectMapperContextResolver.class);
        resources.add(JacksonJsonProvider.class);
        resources.add(ServiceResource.class);
        return resources;
    }
}

My serviceResource

@Path("service")
public class ServiceResource {

    @Path("/forecast/stocks/{modelId}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Value> getStocks(@PathParam("modelId") String modelId, @QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate) {
        try {
            DateTime datetimeStart = formatStringToDatetime(startDate);
            DateTime datetimeEnd = formatStringToDatetime(endDate);
            return logicClass.getStocks(modelId, datetimeStart, datetimeEnd);
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Error calling /hydromax/forecast/stocks", e);
            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
        }
    }

}

And the Value object

public class Value {

    private DateTime date;
    private Float value;

    public Value() {
    }

    //getter and setter

}

Update

I have added the following code inside ApplicationConfig

@Override
public Map<String, Object> getProperties() {
    Map<String, Object> props = new HashMap<>();
    props.put("jersey.config.server.disableMoxyJson", true);
    return props;
}

My DateTime is now transformed to

"date":{"dayOfMonth":16,"dayOfWeek":4,"era":1,"year":2017,"dayOfYear":47,"weekOfWeekyear":7,"secondOfMinute":0,"millisOfSecond":0,"weekyear":2017,"monthOfYear":2,"hourOfDay":10,"minuteOfHour":0,"yearOfEra":2017,"yearOfCentury":17,"centuryOfEra":20,"millisOfDay":36000000,"secondOfDay":36000,"minuteOfDay":600,"millis":1487235600000,"zone":{"fixed":false,"uncachedZone":{"fixed":false,"cachable":true,"id":"Europe/Paris"},"id":"Europe/Paris"},"chronology":{"zone":{"fixed":false,"uncachedZone":{"fixed":false,"cachable":true,"id":"Europe/Paris"},"id":"Europe/Paris"}},"afterNow":false,"beforeNow":true,"equalNow":false} 

And the first time I call the service after deployment, I have this error

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: com/fasterxml/jackson/module/jaxb/JaxbAnnotationIntrospector


回答1:


You are probably missing the jackson-jaxrs-json-provider module in your application.

This module is the Jackson JSON provider for JAX-RS implementations, such as Jersey and RESTeasy.

A ContextResolver for ObjectMapper is only required if you need to customize the ObjectMapper for the Jackson JSON provider. But the ContextResolver won't do anything if the Jackson provider is not registered.


Here's the dependency you need:

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.8.8</version>
</dependency>

If you are not using Maven, add jackson-jaxrs-json-provider-2.8.8.jar to the classpath.

Then register JacksonJsonProvider (using only Jackson annotations) or JacksonJaxbJsonProvider (using both Jackson and JAXB annotations), according to your needs.



来源:https://stackoverflow.com/questions/44652189/deserialize-datetime-joda-with-jackson

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!