jackson配置类
我的jackson配置类如下,其中serializerByType(LocalDateTime.class, new LocalDateTimeSerializer()) 覆盖了@JsonFormat注解
@Configuration
public class JacksonConfiguration {
public static final DateTimeFormatter optionalDateTimePattern =
(new DateTimeFormatterBuilder()).appendValue(ChronoField.YEAR, 4)
.appendPattern("[-][/]MM[-][/]dd['T'][ ]HH[:]mm[:][ss][,SSS][.SSS]").toFormatter();;
static final ZoneOffset zoneOffset = OffsetDateTime.now(ZoneId.systemDefault()).getOffset();
public JacksonConfiguration() {
}
/**
* 配置和创建ObjectMapper对象
*/
public static Jackson2ObjectMapperBuilder createJackson2ObjectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
return customizeBuilder(builder).serializerByType(LocalDateTime.class, new LocalDateTimeSerializer());
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return (builder) -> {
// serializerByType(LocalDateTime.class, new LocalDateTimeSerializer()) 覆盖了@JsonFormat注解
customizeBuilder(builder).serializerByType(LocalDateTime.class, new LocalDateTimeSerializer());
};
}
private static Jackson2ObjectMapperBuilder customizeBuilder(Jackson2ObjectMapperBuilder builder) {
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer())
// 将日期时间序列化为时间戳(以毫秒表示),而不是默认的日期时间字符串格式,如果已经设置了serializerByType则会失效
.featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
// 允许将单个值解析为数组。这意味着如果 JSON 中的某个属性期望是数组类型,但实际上只有一个值,那么它也会被解析为数组。
.featuresToEnable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
// 解开包装在单个值数组中的值。这意味着如果 JSON 中的某个属性被包装在一个只有一个元素的数组中,那么它会被解包成单个值。
.featuresToEnable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
return builder;
}
public static final class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
public LocalDateTimeDeserializer() {
}
public LocalDateTime deserialize(JsonParser p, DeserializationContext context) throws IOException {
// 时间戳格式
if (StringUtils.isNumeric(p.getValueAsString())) {
long timestamp = Long.parseLong(p.getValueAsString());
// 带毫秒
if (p.getValueAsString().length() == 13) {
return Instant.ofEpochMilli(timestamp).atZone(JacksonConfiguration.zoneOffset).toLocalDateTime();
}
// 不带毫秒
else {
return Instant.ofEpochSecond(timestamp).atZone(JacksonConfiguration.zoneOffset).toLocalDateTime();
}
} else {
// 2023-09-08 16:12:25 或 2023-09-08T16:12:25 或 2023-09-08 16:12:25.456 格式
String dateTimeString = p.getValueAsString();
if (StringUtils.isNotEmpty(dateTimeString)) {
return LocalDateTime.parse(dateTimeString, optionalDateTimePattern);
} else {
return null;
}
}
}
}
public static final class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
public LocalDateTimeSerializer() {
}
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
}
}
实体类
当我在LocalDateTime类型的属性上使用@JsonForMat失效
public class TestDTO {
@JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime localDateTime;
public LocalDateTime getLocalDateTime() {
return localDateTime;
}
public void setLocalDateTime(LocalDateTime localDateTime) {
this.localDateTime = localDateTime;
}
@Override
public String toString() {
return "TestDTO{" + "localDateTime=" + localDateTime + '}';
}
}
接口
调用接口的返回值是时间戳,而不是 yyyy/MM/dd HH:mm:ss
@PostMapping("/test7")
public TestDTO test7() {
TestDTO testDTO = new TestDTO();
testDTO.setLocalDateTime(LocalDateTime.now());
return testDTO;
}
返回值:
{
"localDateTime": 1706086696221
}
一种解决方法
改用 @JsonSerialize
注解
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime localDateTime;
在外面定义一个LocalDateTimeSerializer,在serialize
方法中定义要输出的格式
package com.xjhqre.config;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(value));
}
}