如何解决如何使用 Spring Boot 和 Jackson 在没有纳秒的情况下序列化 Instant?
Spring 使用 Jackson 的 InstantSerializer 像这样写出我的 Instant 字段:
now: "2021-04-07T10:51:53.043320Z"
不过,我不想要纳秒 - 只是毫秒。我猜是设置应用程序属性
spring.jackson.serialization.write-date-timestamps-as-nanoseconds=false
会实现这一点,但没有区别。
如何告诉 Spring/Jackson 在序列化 Instants 时省略纳秒?
(我使用的是 Spring Boot 2.2.11.RELEASE)
更新
我最终根据 this answer 得到了它。我不得不使用已弃用的 JSR310Module 而不是 JavaTimeModule,并覆盖 createContextual(...) 方法以强制它始终使用我的序列化程序。
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
JSR310Module jsr310Module = new JSR310Module();
jsr310Module.addSerializer(Instant.class,new MyInstantSerializer());
objectMapper.registerModule(jsr310Module);
return objectMapper;
}
private static class MyInstantSerializer extends InstantSerializer {
public MyInstantSerializer() {
super(InstantSerializer.INSTANCE,false,new DateTimeFormatterBuilder().appendInstant(3).toFormatter());
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov,BeanProperty property) {
return this;
}
}
这也有效(基于 Volodya's answer below):
@Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomTimeSerialization() {
return jacksonObjectMapperBuilder ->
jacksonObjectMapperBuilder.serializerByType(Instant.class,new JsonSerializer<Instant>() {
private final DateTimeFormatter formatter =
new DateTimeFormatterBuilder().appendInstant(3).toFormatter();
@Override
public void serialize(
Instant instant,JsonGenerator generator,SerializerProvider provider) throws IOException {
generator.writeString(formatter.format(instant));
}
});
}
解决方法
为此,您可以使用 @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS]")
完整示例:
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
public class Message {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS]")
private final LocalDateTime dateTime;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS]")
private final ZonedDateTime zonedDateTime;
public Message(ZonedDateTime zonedDateTime) {
this(zonedDateTime.toLocalDateTime(),zonedDateTime);
}
public Message(LocalDateTime dateTime,ZonedDateTime zonedDateTime) {
this.dateTime = dateTime;
this.zonedDateTime = zonedDateTime;
}
public LocalDateTime getDateTime() {
return dateTime;
}
public ZonedDateTime getZonedDateTime() {
return zonedDateTime;
}
}
测试:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import java.time.*;
import java.time.temporal.ChronoUnit;
import static org.junit.jupiter.api.Assertions.*;
@JsonTest
class MessageTest {
@Autowired
ObjectMapper mapper;
@Test
public void serializationTest() throws JsonProcessingException {
final LocalDate date = LocalDate.of(2000,Month.JANUARY,1);
final LocalTime time = LocalTime.of(12,20,10).plus(123,ChronoUnit.MILLIS);
final Message message = new Message(ZonedDateTime.of(date,time,ZoneId.systemDefault()));
final String res = mapper.writeValueAsString(message);
assertEquals("{\"dateTime\":\"2000-01-01T12:20:10.123\",\"zonedDateTime\":\"2000-01-01T12:20:10.123\"}",res);
}
}
更新:
如果你想集中配置它,你可以:
- 尝试将日期格式设置为您的 ObjectMapper,如here
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"));
- 按照描述自定义您的映射器here
@SpringBootApplication
public class InstantSerializerApplication {
public static void main(String[] args) {
SpringApplication.run(InstantSerializerApplication.class,args);
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomTimeSerialization() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.serializerByType(ZonedDateTime.class,new JsonSerializer<ZonedDateTime>() {
@Override
public void serialize(ZonedDateTime zonedDateTime,JsonGenerator jsonGenerator,SerializerProvider serializerProvider) throws IOException {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
jsonGenerator.writeString(formatter.format(zonedDateTime));
}
});
}
}
,
更好的方法是
@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private final ZonedDateTime zonedDateTime;
有关详细信息,请参阅此 question
的公认答案版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。