通过Jackson的String转joda.DateTime的采坑记录

希-望圆满-
背景:最近公司在做秒杀活动,刚好我做的活动时间处理那块;其中一块是负责把前台的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.datatypegroupId>
      <artifactId>jackson-datatype-jodaartifactId>
      <version>2.9.8version>
dependency>

这个jar包,反序列化的结果会不一样哦

你可能感兴趣的:(采坑记录)