Spring Boot中Jackson日期序列化异常问题及配置求助
问题
在Spring Boot Web项目中使用Jackson时遇到一个问题:期望接口返回如下格式的响应:
{ "date": "string of date" }
但实际返回的却是:
[ 0: java.sql.date, 1: long number of timestamp ]
请问该如何配置Spring Boot来避免这个问题?
我的配置类代码
@Configuration public class BootConfiguration { @Bean @Primary public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @Bean public JavaTimeModule javaTimeModule() { return new JavaTimeModule(); } @Bean public Jdk8Module jdk8TimeModule() { return new Jdk8Module(); } @Bean public CoreJackson2Module coreJackson2Module() { return new CoreJackson2Module(); } @Bean public OAuth2AuthorizationServerJackson2Module authorizationServerJackson2Module(){ return new OAuth2AuthorizationServerJackson2Module(); } public List<Module> securityModules(){ ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader(); return SecurityJackson2Modules.getModules(classLoader); } @Bean @Primary @Order(Ordered.HIGHEST_PRECEDENCE) public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper().findAndRegisterModules(); mapper.registerModule(coreJackson2Module()); mapper.registerModule(javaTimeModule()); mapper.registerModule(jdk8TimeModule()); mapper.registerModules(securityModules()); mapper.registerModule(authorizationServerJackson2Module()); mapper.addMixIn(UserPrincipal.class, Object.class); return mapper; } }
相关控制器方法
@GetMapping(value = "/authentications", params = {"pge","lmt", "slug"}) public ResponseEntity<?> getLastLogins( Authentication authentication, @RequestParam("lmt")Integer limit, @RequestParam("pge")Integer page, @RequestParam("slug")String slug){ return new ResponseEntity<>(loginManager.findAllAuthentications(authentication.getName(),slug,limit,page), HttpStatus.OK); } }
包含目标属性的实体类
@Data public class User implements Serializable { private String firstName; private String lastName; private Date date; private Role role; }
解决方案
问题根源是**java.sql.Date类型未被Jackson正确序列化**,默认规则会将其转为包含SQL日期对象和时间戳的数组。以下是几种可行的解决方式:
方式一:在自定义ObjectMapper中配置日期序列化规则
修改你的objectMapper Bean,添加SQL日期模块注册和全局日期格式化配置:
@Bean @Primary @Order(Ordered.HIGHEST_PRECEDENCE) public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper().findAndRegisterModules(); // 注册SQL日期处理模块,专门处理java.sql.Date类型 mapper.registerModule(new SqlDateModule()); // 关闭时间戳序列化,指定日期格式 mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd")); // 可自定义格式 mapper.registerModule(coreJackson2Module()); mapper.registerModule(javaTimeModule()); mapper.registerModule(jdk8TimeModule()); mapper.registerModules(securityModules()); mapper.registerModule(authorizationServerJackson2Module()); mapper.addMixIn(UserPrincipal.class, Object.class); return mapper; }
注:
SqlDateModule属于Jackson的SQL日期处理模块,Spring Boot Starter通常已默认引入相关依赖(jackson-datatype-sql)。
方式二:在实体类字段上添加注解指定格式
如果仅需针对单个字段处理,直接在User类的date字段上添加@JsonFormat注解:
@Data public class User implements Serializable { private String firstName; private String lastName; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") private Date date; private Role role; }
方式三:通过Spring Boot配置文件全局配置
在application.yml(或application.properties)中添加Jackson全局日期配置:
spring: jackson: serialization: write-dates-as-timestamps: false date-format: yyyy-MM-dd
这种方式无需修改配置类,但如果自定义了ObjectMapper,需要确保自定义Mapper继承这些配置(可通过注入Jackson2ObjectMapperBuilder来实现)。
额外注意事项
- 确认实体类中的
Date是java.sql.Date还是java.util.Date:前者需要SqlDateModule,后者使用默认配置或JavaTimeModule即可处理。 - 建议优先使用Java 8+的时间API(如
LocalDate),JavaTimeModule已内置完善的序列化规则,能避免旧Date类的兼容性问题。
内容的提问来源于stack exchange,提问作者Mukendi Emmanuel
相关产品推荐
相关产品推荐

