2017-07-19 75 views
1

我正在使用Angular日期選擇器向我的MVC控制器發送日期,使用ISO Date日期對象/ 時間傑克遜從ISO反序列化Joda LocalDate DateTime

關於反序列化java.util.Date它的作用就像一個魅力,Hibernate會關心在插入記錄時將那個時間切割成普通日期。

但現在我正在從java.util.Date轉換到org.joda.time.[APPROPRIATE_CLASS_HERE]我正面臨着這個反序列化問題。

我的理解是,如果我在我的DTO中強制DateTime,Jackson會正確反序列化它們,而我更傾向於在目標類型爲Date時刪除時間信息。

E.g.

public class UserDto { 

    private LocaLDate passwordExpirationDate; 

} 


{ 
    "username":"9493", 
    "completeName":"ljdjf", 
    "email":"[email protected]", 
    "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 

問題是:有一個聰明的辦法讓傑克遜可以通過簡單的剝離,在默認情況下,部分時間/當前時區DateTime對象解碼成喬達LocalDate

注: - 我已經有傑克遜喬達模塊依賴 - 傑克遜是2.8.9 - 我不得不使用Java 7。在相關的Java 8項目我沒有這樣的問題java.time東西(和傑克遜JSR310模塊)

回答

1

在我的Spring上下文配置以下工作對我

<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" id="pnxObjectMapper"> 
    <property name="deserializersByType"> 
     <map key-type="java.lang.Class"> 
      <entry> 
       <key> 
        <value>org.joda.time.LocalDate</value> 
       </key> 
       <bean class="com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer"> 
        <constructor-arg> 
         <util:constant static-field="com.fasterxml.jackson.datatype.joda.cfg.FormatConfig.DEFAULT_DATETIME_PARSER" /> 
        </constructor-arg> 
       </bean> 
      </entry> 
     </map> 
    </property> 
</bean> 

說明:加載JodaModule,它定義了一個解串器LocalDate小號理所當然採用的ISO日期只格式之前,我力彈簧改變格式化程序構建串行器時

1

根據錯誤信息,日期/時間輸入爲2017-07-13T10:00:00.000ZLocalDate默認情況下無法處理。

您可以通過在LocalDate領域使用com.fasterxml.jackson.annotation.JsonFormat註解配置此格式:

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

這將使傑克遜正確地解析日期。

+0

任何機會,在全球範圍內應用此之後... ... EHM類路徑範圍內? –

+0

另外...我剛完成測試提議的解決方案。我會發布它作爲答案。如果您可以幫助我將上述內容應用於LocalDate類型的每個屬性,我將授予您接受的答案,因爲我不喜歡我的解決方案 –

+0

如何配置傑克遜?你是手動創建ObjectMapper還是使用Angular特定的配置文件來配置它? – 2017-07-19 17:21:19

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配置

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

它應該工作