希-望圆满-
背景:最近公司在做秒杀活动,刚好我做的活动时间处理那块;其中一块是负责把前台的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包,反序列化的结果会不一样哦