无法使用Jackson反序列化ZonedDateTime

时间:2016-01-20 08:06:03

标签: java jackson java-time

我使用Jersey和Jackson作为JSON提供者。我可以将ZonedDateTime序列化为JSON,但是当我想要反序列化时,它会给出如下错误。

请您帮我说明完成反序列化工作所需的确切配置。

  

引起:com.fasterxml.jackson.databind.JsonMappingException:无法从字符串值实例化类型[simple type,class java.time.ZonedDateTime]的值(' 2016-01-21T21:00:00Z& #39);没有单字符串构造函数/工厂方法

我的映射器配置如下:

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper MAPPER;

    public ObjectMapperContextResolver() {
        MAPPER = new ObjectMapper();
        //This would add JSR310 (Datetime) support while converting date to JSON using JAXRS service
        MAPPER.registerModule(new JavaTimeModule());
        //Below line would disable use of timestamps (numbers), 
        //and instead use a [ISO-8601 ]-compliant notation, which gets output as something like: "1970-01-01T00:00:00.000+0000".
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

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

1 个答案:

答案 0 :(得分:1)

我发现了问题,实际上问题不是使用标准的jackson提供程序进行反序列化。在我的例子中,我使用Jersey客户端获取JSON,然后使用readEntity方法反序列化。

问题是,泽西客户端不知道jsr310模块,因此通过注册已添加jsr310的contextresolver解决了这个问题。简而言之,如果使用普通的jackson提供程序,则不需要为ZonedDateTime的seralization和反序列化做任何事情。

以下是我在此引用的参考代码,以便更清晰。

public class RESTClientImpl{

    /*
     * ***This is very important, JacksonJsonProvider is the implementation of
     * MessageBodyWriter/Reader which is required for "readEntity" method, 
     * else it would throw MessageBodyWriter/Reader not found exception
     * 
     * https://jersey.java.net/documentation/latest/message-body-workers.html#mbw.ex.client.mbr.reg
     *
     * Registering of ObjectMapperContextResolver is important as we have registered JSR310 module there and without registering this, 
     * Jersey client is not aware of JSR310 module, so it will not be able to de-serialize ZonedDateTime
     */
    private final Client client = ClientBuilder.newClient(new ClientConfig().register(LoggingFilter.class)).register(JacksonJsonProvider.class)
            .register(ObjectMapperContextResolver.class);

    public User get(URI uri) {
        WebTarget webTarget = client.target(uri);

        Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
        Response response = invocationBuilder.get();    
        User user = response.readEntity(User.class);
        return user;
    }
}


@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper MAPPER;

    public ObjectMapperContextResolver() {
        MAPPER = new ObjectMapper();
        //This would add JSR310 (Datetime) support while converting date to JSON using JAXRS service
        MAPPER.registerModule(new JavaTimeModule());
        //Below line would disable use of timestamps (numbers), 
        //and instead use a [ISO-8601 ]-compliant notation, which gets output as something like: "1970-01-01T00:00:00.000+0000".
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Object.class, new ZonedDateTimeDeserializer());
        MAPPER.registerModule(simpleModule);
    }

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