希-望圓滿-
背景:最近公司在做秒殺活動,剛好我做的活動時間處理那塊;其中一塊是負責把前臺的json通過Jackson轉爲joda.DateTime
,但是就在這中間出現了問題
問題描述
直接把"2019-10-24 00:00:00"
通過Jackson轉爲DateTime
時,會產生如下錯誤:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `org.joda.time.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('2019-10-24 00:00:00'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.joda.time.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('2019-10-24 00:00:00')
at ...
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.joda.time.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('2019-10-24 00:00:00')
at ...
感覺是構造器出了問題,導入了jackson-core
,jackson-databind
,jackson-datatype-joda
三個包後,同時,又在application.properties
中配置了time-format:spring.jackson.joda-date-time-format="yyyy-MM-dd HH:mm:ss"
後,重新運行,發現仍然有問題:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid format: "2019-10-24 00:00:00" is malformed at " 00:00:00"; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid format: "2019-10-24 00:00:00" is malformed at " 00:00:00" (through reference chain: com.savannah.service.model.PromoDTO["startDate"])
at ...
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid format: "2019-10-24 00:00:00" is malformed at " 00:00:00" (through reference chain: com.savannah.service.model.PromoDTO["startDate"])
at ...
Caused by: java.lang.IllegalArgumentException: Invalid format: "2019-10-24 00:00:00" is malformed at " 00:00:00"
at...
可以看出,是格式轉換不正確,但是我找了好久也沒找到正確轉換格式的辦法
產生原因
容易發現,Jackson內置的沒有轉換·joda.DateTime`的方式,需要通過第三個Jar包或者自定義序列化/反序列化來解決這個問題
解決方案
- 自定義Jackson中實體類的序列化和反序列化方式:
public class CustomDateSerializer extends JsonSerializer<DateTime> {
private static DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider arg2) throws IOException {
gen.writeString(formatter.print(value));
}
}
public class CustomDateDeserializer extends JsonDeserializer<DateTime> {
private static DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
@Override
public DateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String s = node.asText();
return DateTime.parse(s, formatter);
}
}
- 在DateTime類型的字段中加入註解:
/**
* 秒殺開始時間
*/
@JsonSerialize(using = CustomDateSerializer.class)
@JsonDeserialize(using = CustomDateDeserializer.class)
private DateTime startDate;
/**
* 秒殺活動結束時間
*/
@JsonSerialize(using = CustomDateSerializer.class)
@JsonDeserialize(using = CustomDateDeserializer.class)
private DateTime endDate;
這樣的話基本就完工了,同時也可以嘗試加入:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.9.8</version>
</dependency>
這個jar包,反序列化的結果會不一樣哦