REST API响应中Timestamp变为毫秒数,求ISO格式恢复方案
问题背景
引入公司内部库后,REST API响应中的Timestamp字段从之前的ISO字符串格式2022-06-30T22:39:22.235+0000变成了毫秒数格式1656628762235。已尝试在DTO字段添加@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSXXX")注解,以及在YAML配置中设置spring.jackson.serialization.write-dates-as-timestamps: true,但均未生效。当前环境版本:jackson-datatype-jsr310 2.9.10、jackson-databind 2.9.10、spring-boot-2.1.11.RELEASE,DTO中使用的是java.sql.Timestamp类型。
可行解决方案
1. 修正配置参数值
你之前的配置参数写反了:spring.jackson.serialization.write-dates-as-timestamps: true会强制将日期类型序列化为时间戳,改成false才会输出字符串格式:
spring: jackson: serialization: write-dates-as-timestamps: false
2. 为Timestamp字段显式指定序列化器
由于java.sql.Timestamp的序列化逻辑和Java 8时间类型略有不同,加上内部库可能覆盖了默认规则,可以直接在字段上指定序列化器:
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer; import java.sql.Timestamp; // 在DTO的Timestamp字段上添加注解 @JsonSerialize(using = InstantSerializer.class) private Timestamp createdDate; @JsonSerialize(using = InstantSerializer.class) private Timestamp modifiedDate;
InstantSerializer会将Timestamp转换为标准的ISO-8601格式字符串,和你之前的格式一致。
3. 自定义Jackson全局配置类
如果内部库的Jackson配置优先级更高,创建一个自定义配置类强制覆盖规则:
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.text.SimpleDateFormat; @Configuration public class JacksonDateConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jacksonDateCustomizer() { return builder -> { // 禁用时间戳序列化 builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 注册JSR310模块,处理SQL和Java 8时间类型 builder.modules(new JavaTimeModule()); // 设置全局日期格式 builder.simpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); }; } }
这个配置类会优先加载,确保日期字段按指定格式输出。
4. 排查并覆盖内部库的Jackson配置
内部库可能自带了自定义的ObjectMapper或Jackson模块,覆盖了默认行为。可以排查内部库是否存在以下情况:
- 自定义
ObjectMapper并设置了WRITE_DATES_AS_TIMESTAMPS为true - 注册了自定义的日期序列化模块
如果存在上述情况,可以在项目中创建一个标记@Primary的ObjectMapper Bean,强制让项目的配置优先级更高:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.text.SimpleDateFormat; @Bean @Primary public ObjectMapper customObjectMapper() { ObjectMapper mapper = new ObjectMapper(); // 禁用时间戳输出 mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 注册JSR310模块 mapper.registerModule(new JavaTimeModule()); // 设置日期格式 mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")); return mapper; }
验证
每完成一项配置修改后,重启服务并测试API响应,确认createdDate和modifiedDate字段恢复为ISO字符串格式。
内容的提问来源于stack exchange,提问作者Subhamoy Ghosh

