自定义Jackson配置,解决LocalDateTime序列化问题
Sync All Branches to GitHub / sync (push) Successful in 3s

This commit is contained in:
hanfuye
2026-01-06 17:28:59 +08:00
parent 275e7dded9
commit 5c18560351
5 changed files with 120 additions and 26 deletions
@@ -0,0 +1,72 @@
package top.crushtj.xiaoyishu.auth.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.YearMonthDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.YearMonthSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.crushtj.framework.common.constant.DateConstants;
import top.crushtj.framework.common.utils.JsonUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.TimeZone;
/**
* @author ayi
* @version V1.0
* @title JacksonConfig
* @description jackson 配置类
* @date 2026/01/06
*/
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 忽略未知属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 设置凡是为 null 的字段,返参中均不返回,请根据项目组约定是否开启
// objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 设置时区
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// JavaTimeModule 用于指定序列化和反序列化规则
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 支持 LocalDateTime、LocalDate、LocalTime
// 支持 LocalDateTime、LocalDate、LocalTime
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateConstants.DATE_FORMAT_Y_M_D_H_M_S));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateConstants.DATE_FORMAT_Y_M_D_H_M_S));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateConstants.DATE_FORMAT_Y_M_D));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateConstants.DATE_FORMAT_Y_M_D));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateConstants.DATE_FORMAT_H_M_S));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateConstants.DATE_FORMAT_H_M_S));
// 支持 YearMonth
javaTimeModule.addSerializer(YearMonth.class, new YearMonthSerializer(DateConstants.DATE_FORMAT_Y_M));
javaTimeModule.addDeserializer(YearMonth.class, new YearMonthDeserializer(DateConstants.DATE_FORMAT_Y_M));
objectMapper.registerModule(javaTimeModule);
JsonUtils.init(objectMapper);
return objectMapper;
}
}
@@ -1,5 +1,8 @@
package top.crushtj.xiaoyishu.auth.controller; package top.crushtj.xiaoyishu.auth.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog; import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog;
import top.crushtj.framework.common.response.Response; import top.crushtj.framework.common.response.Response;
@@ -7,8 +10,6 @@ import top.crushtj.xiaoyishu.auth.vo.User;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import org.springframework.web.bind.annotation.GetMapping;
/** /**
* *
* @Title: TestController * @Title: TestController
@@ -31,4 +32,10 @@ public class TestController {
.build()); .build());
} }
@PostMapping("/test2")
@ApiOperationLog(description = "测试接口2")
public Response<User> test2(@RequestBody User user) {
return Response.success(user);
}
} }
@@ -1,11 +1,12 @@
package top.crushtj.xiaoyishu.auth.vo; package top.crushtj.xiaoyishu.auth.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import lombok.Builder;
import lombok.Data;
/** /**
* *
@@ -17,6 +18,8 @@ import lombok.Data;
@Data @Data
@Builder @Builder
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable { public class User implements Serializable {
private Long id; private Long id;
private String name; private String name;
@@ -1,5 +1,7 @@
package top.crushtj.framework.common.constant; package top.crushtj.framework.common.constant;
import java.time.format.DateTimeFormatter;
/** /**
* @Title: DateConstants * @Title: DateConstants
* @Description: 日期常量 * @Description: 日期常量
@@ -8,7 +10,22 @@ package top.crushtj.framework.common.constant;
*/ */
public interface DateConstants { public interface DateConstants {
/** /**
* 年-月-日 时:分:秒 * DateTimeFormatter年-月-日 时:分:秒
*/ */
String Y_M_D_H_M_S_FORMAT = "yyyy-MM-dd HH:mm:ss"; DateTimeFormatter DATE_FORMAT_Y_M_D_H_M_S = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* DateTimeFormatter:年-月-日
*/
DateTimeFormatter DATE_FORMAT_Y_M_D = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/**
* DateTimeFormatter:时:分:秒
*/
DateTimeFormatter DATE_FORMAT_H_M_S = DateTimeFormatter.ofPattern("HH:mm:ss");
/**
* DateTimeFormatter:年-月
*/
DateTimeFormatter DATE_FORMAT_Y_M = DateTimeFormatter.ofPattern("yyyy-MM");
} }
@@ -1,17 +1,10 @@
package top.crushtj.framework.common.utils; package top.crushtj.framework.common.utils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 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.SneakyThrows; import lombok.SneakyThrows;
import top.crushtj.framework.common.constant.DateConstants;
/** /**
* *
@@ -21,24 +14,26 @@ import top.crushtj.framework.common.constant.DateConstants;
* @Date: 2025/11/21 * @Date: 2025/11/21
*/ */
public class JsonUtils { public class JsonUtils {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static { static {
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
OBJECT_MAPPER.registerModules(new JavaTimeModule());
// JavaTimeModule 用于指定序列化和反序列化规则
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 支持 LocalDateTime
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateConstants.Y_M_D_H_M_S_FORMAT)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateConstants.Y_M_D_H_M_S_FORMAT)));
OBJECT_MAPPER.registerModules(javaTimeModule); // 解决 LocalDateTime 的序列化问题
} }
/**
* 初始化:统一使用 Spring Boot 个性化配置的 ObjectMapper
*
* @param objectMapper
*/
public static void init(ObjectMapper objectMapper) {
OBJECT_MAPPER = objectMapper;
}
/** /**
* 将对象转换为 JSON 字符串 * 将对象转换为 JSON 字符串
* *
* @param obj 要转换的对象 * @param obj 要转换的对象
* @return JSON 字符串 * @return JSON 字符串
*/ */