JacksonConfig.java 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package com.poyee.config;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import com.fasterxml.jackson.databind.SerializationFeature;
  4. import com.fasterxml.jackson.databind.module.SimpleModule;
  5. import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
  9. import java.time.LocalDateTime;
  10. import java.time.format.DateTimeFormatter;
  11. /**
  12. * 全局 Jackson 配置
  13. * <p>
  14. * 注册时区感知序列化器 {@link LocalDateTimeZoneSerializerConfig}:
  15. * 所有响应中的 {@link LocalDateTime} 字段将根据请求头 {@code Accept-Language}
  16. * 自动从 UTC 转换为客户端对应的区域时间后输出。
  17. * </p>
  18. *
  19. * <p>
  20. * 注意:不使用 {@code JavaTimeModule} 注册自定义序列化器,
  21. * 因为 Spring Boot 自动配置的 {@code Jackson2ObjectMapperBuilder} 已注册过 {@code JavaTimeModule},
  22. * Jackson 的模块去重机制会导致第二次注册同类型模块被静默跳过。
  23. * 改用独立命名的 {@code SimpleModule} 可绕过去重检查,确保自定义序列化器生效。
  24. * </p>
  25. */
  26. @Configuration
  27. public class JacksonConfig {
  28. private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
  29. @Bean
  30. public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
  31. // 保留 Spring Boot 自动配置的所有默认模块,在此基础上叠加
  32. ObjectMapper mapper = builder.createXmlMapper(false).build();
  33. // 使用 SimpleModule(独立类名)注册,绕过 Jackson 对 JavaTimeModule 的去重跳过机制
  34. SimpleModule overrideModule = new SimpleModule("LocalDateTimeZoneOverride");
  35. // 序列化:UTC LocalDateTime → 客户端时区时间(根据 Accept-Language 自动转换)
  36. overrideModule.addSerializer(LocalDateTime.class, new LocalDateTimeZoneSerializerConfig());
  37. // 反序列化:客户端传入时间字符串 → LocalDateTime(业务层保证传入 UTC)
  38. overrideModule.addDeserializer(
  39. LocalDateTime.class,
  40. new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN))
  41. );
  42. mapper.registerModule(overrideModule);
  43. // 禁用将时间序列化为时间戳
  44. mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
  45. return mapper;
  46. }
  47. }