使用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等时间戳类型需要手动定义后才允许进行序列化和反序列化,目前我提供的方案只是最基础简陋的使用方案,具体方案待后续开发需要使用到在更新!