杰克逊从ISO DateTime反序化Joda LocalDate

时间:2017-07-19 16:55:28

标签: java datetime jackson jodatime date-parsing

我使用Angular日期选择器向我的MVC控制器发送日期,使用Javascript Date对象,这是ISO日期/ 时间

在反序列化java.util.Date时,它就像一个魅力,而Hibernate会关心在插入记录时将Date时间缩短到一个简单的日期。

但是现在我正在从java.util.Date过渡到org.joda.time.[APPROPRIATE_CLASS_HERE]我正面临着这个反序列化问题。

我的理解是,如果我在我的DTO中强制DateTime,杰克逊会正确地反序列化它们,而我更愿意在目标类型为日期时删除时间信息。

E.g。

public class UserDto {

    private LocaLDate passwordExpirationDate;

}


{
   "username":"9493",
   "completeName":"ljdjf",
   "email":"wesf@dsgfds",
   "cultureId":"IT",
   "enabled":false,
   "passwordExpirationDate":"2017-07-13T10:00:00.000Z",
   "accountExpirationDate":"2017-07-20T10:00:00.000Z"
}

相反,我得到了这个:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid format: "2017-07-13T10:00:00.000Z" is malformed at "T10:00:00.000Z"; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid format: "2017-07-13T10:00:00.000Z" is malformed at "T10:00:00.000Z" (through reference chain: it.phoenix.web.data.dtos.admin.profile.UserDTO["passwordExpirationDate"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:244) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid format: "2017-07-13T10:00:00.000Z" is malformed at "T10:00:00.000Z" (through reference chain: it.phoenix.web.data.dtos.admin.profile.UserDTO["passwordExpirationDate"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388) ~[jackson-databind-2.8.9.jar:2.8.9]
Caused by: java.lang.IllegalArgumentException: Invalid format: "2017-07-13T10:00:00.000Z" is malformed at "T10:00:00.000Z"
    at org.joda.time.format.DateTimeFormatter.parseLocalDateTime(DateTimeFormatter.java:900) ~[joda-time-2.9.9.jar:2.9.9]
    at org.joda.time.format.DateTimeFormatter.parseLocalDate(DateTimeFormatter.java:844) ~[joda-time-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:39) ~[jackson-datatype-joda-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:15) ~[jackson-datatype-joda-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504) ~[jackson-databind-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104) ~[jackson-databind-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:357) ~[jackson-databind-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) ~[jackson-databind-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814) ~[jackson-databind-2.8.9.jar:2.8.9]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2938) ~[jackson-databind-2.8.9.jar:2.8.9]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    ... 92 more

问题是:有没有一种聪明的方法可以让Jackson通过简单地剥离默认/当前时区的时间部分将DateTime对象解码为Joda LocalDate

注意:   - 我已经拥有Jackson Joda模块依赖   - 杰克逊是2.8.9   - 我被迫使用Java 7.在一个相关的Java 8项目中,我对java.time的东西(和Jackson JSR310模块)没有这样的问题

3 个答案:

答案 0 :(得分:2)

根据错误消息,日期/时间输入为2017-07-13T10:00:00.000Z,默认情况下LocalDate无法处理。

您可以使用com.fasterxml.jackson.annotation.JsonFormat字段中的LocalDate注释来配置此格式:

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private LocalDate passwordExpirationDate;

这将使杰克逊正确地解析日期。

答案 1 :(得分:1)

以下内容在我的Spring上下文配置

中对我有用
> successful      <- qdap::polarity("testing")
> load_openssl_ns <- body(openssl:::print.key)
> fails           <- qdap::polarity("testing")
Error in derive_pubkey(key) : 
  RAW() can only be applied to a 'raw', not a 'list'

说明:在加载JodaModule之前,它定义了var timer = setInterval(()=>{ $scope.$apply(updateClock); }, 1000); updateClock(); .... 正确采用ISO日期格式的反序列化器,我强制Spring在构造序列化器时更改格式化程序

答案 2 :(得分:0)

我认为你在创建ObjectMapper时可以注册一些模块。

public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.registerModule(new JavaTimeModule());
    objectMapper.registerModule(new JodaModule());
    return objectMapper;
}

将它放在Spring Config中的消息转换器

MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper());

// Configuration class
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(mappingJackson2HttpMessageConverter());
}

应该工作后