【异常】使用Jackson序列化LocalDateTime类型报错的解决方法

136 阅读2分钟

使用Jackson序列化LocalDateTime类型报错的解决方法

环境版本

      <!-- 当前环境jdk版本是 java8 -->
      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.11.3</version>
      </dependency>

异常信息

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDateTime` (no Creators, like default constructor, exist): no String-argument constructor/factory method to deserialize from String value ('2023-11-08 11:27:02')
 at [Source: (String)"{"createDate":"2023-11-08 11:27:02","updateDate":"2023-11-08 11:27:02"}"; line: 1, column: 15] (through reference chain: top.shiqudehuiyi.designpattern.vo.BaseVO["createDate"])
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1615)
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
	at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
	at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1408)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:176)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:166)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3468)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3436)

解决方案

全局应用

用于封装一层jackson工具类的实现


import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Data
public class BaseVO {

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
//  @JsonSerialize(using = LocalDateTimeSerializer.class)
  private LocalDateTime createDate;

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
//  @JsonSerialize(using = LocalDateTimeSerializer.class)
  private LocalDateTime updateDate;


  public static void main(String[] args) throws JsonProcessingException {
    String json = "{\"createDate\":\"2023-11-08 11:27:02\",\"updateDate\":\"2023-11-08 11:27:02\"}";
    ObjectMapper objectMapper = new ObjectMapper();
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    objectMapper.registerModule(javaTimeModule);
    BaseVO baseVO = objectMapper.readValue(json, BaseVO.class);
    System.out.println(objectMapper.writeValueAsString(baseVO));
  }
}

局部应用

在局部使用的方式可以通过注解来实现

测试代码
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data;

import java.time.LocalDateTime;

@Data
public class BaseVO {

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
  @JsonSerialize(using = LocalDateTimeSerializer.class)
  private LocalDateTime createDate;
  
  // 格式化时间注解
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  // 反序列化注解
  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
  // 序列化注解
  @JsonSerialize(using = LocalDateTimeSerializer.class)
  private LocalDateTime updateDate;


  public static void main(String[] args) throws JsonProcessingException {
    String json = "{\"createDate\":\"2023-11-08 11:27:02\",\"updateDate\":\"2023-11-08 11:27:02\"}";
    ObjectMapper objectMapper = new ObjectMapper();
    BaseVO baseVO = objectMapper.readValue(json, BaseVO.class);
    System.out.println(objectMapper.writeValueAsString(baseVO));
  }
}

小结

通过以上方案,可以看出来,jackson对于LocalDateTime等时间戳类型需要手动定义后才允许进行序列化和反序列化,目前我提供的方案只是最基础简陋的使用方案,具体方案待后续开发需要使用到在更新!

借鉴引用

Jackson 之 LocalDateTime 序列化与反序列化