如何在Spring-MVC中跳过杰克逊时区校正?

mem*_*und 2 java spring spring-mvc jackson

我想配置jackson为以以下格式输出任何日期/时间值:

spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss

我正在获取许多数据库行,并将它们作为json地图返回。

@RestController
public class MyService {
    @GetMapping
    public List<Map<String, Object>> get(Param params) {
             return jdbcTemplate.queryForList(sql, params);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:数据库和jvm的默认时区为Europe/Berlin,因此为UTC + 2。因此,杰克逊会先自动将接收java.sql.Timestamp到的所有数据库转换为UTC(减去2小时),然后通过json输出它们。

mysql数据库本身中,它是一种datetime类型。

但是我只想让杰克逊按原样输出时间戳,而无需事先转换!是否可以跳过时区校正?

我只想忽略时区而不进行交谈。剪下来

cas*_*lin 5

方法1:设置默认时区

您可以使用所使用的日期格式设置时区ObjectMapper。它将用于Date和子类:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));

ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(dateFormat);
Run Code Online (Sandbox Code Playgroud)

在Spring应用程序中,要配置ObjectMapper,您可以执行以下操作:

@Bean
public ObjectMapper objectMapper() {

    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    dateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));

    ObjectMapper mapper = new ObjectMapper();
    mapper.setDateFormat(dateFormat);
    return mapper;
}
Run Code Online (Sandbox Code Playgroud)

在Spring Boot中,您可以使用属性spring.jackson.time-zone来定义时区:

spring.jackson.time-zone: Europe/Berlin
Run Code Online (Sandbox Code Playgroud)

有关通用应用程序属性的更多详细信息,请参阅文档

方法2:使用Java 8日期和时间API

除了使用之外Timestamp,您还可以考虑LocaDateTime使用JSR-310。它是用Java 8引入了“本地”日期和时间类(LocalDateTimeLocalDateLocalTime)不依赖于任何一个地区或时区。从LocalDateTime文档中:

此类不存储或表示时区。相反,它是对用于生日的日期的描述,以及在墙上时钟上看到的本地时间。如果没有其他信息(例如偏移或时区),则无法在时间线上表示时刻。

答案将为您提供有关新日期和时间类别的更多详细信息。

Jackson的模块支持JSR-310类型。将其添加到您的依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

然后JavaTimeModule在您的ObjectMapper实例中注册模块:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Run Code Online (Sandbox Code Playgroud)

大多数JSR-310类型将使用标准ISO-8601字符串表示形式进行序列化。如果需要自定义格式,则可以使用自己的序列化器和解串器实现。有关详细信息,请参见文档


mem*_*und 5

最后发现最简单的方法是将 jacksons ObjectMapperUTC默认使用)时区设置为 jvm 默认值:

@Bean
public Jackson2ObjectMapperBuilderCustomizer init() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder builder) {
            builder.timeZone(TimeZone.getDefault());
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

如果有人知道如何通过使用spring.jackson.time-zoneapplication.property来实现相同的目标,我将不胜感激。