Java Jackson 在 Spring Boot 中错误地序列化了 ZonedDateTime
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39086472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson serializes a ZonedDateTime wrongly in Spring Boot
提问by jbx
I have a simple application with Spring Boot and Jetty. I have a simple controller returning an object which has a Java 8 ZonedDateTime
:
我有一个带有 Spring Boot 和 Jetty 的简单应用程序。我有一个简单的控制器返回一个具有 Java 8 的对象ZonedDateTime
:
public class Device {
// ...
private ZonedDateTime lastUpdated;
public Device(String id, ZonedDateTime lastUpdated, int course, double latitude, double longitude) {
// ...
this.lastUpdated = lastUpdated;
// ...
}
public ZonedDateTime getLastUpdated() {
return lastUpdated;
}
}
In my RestController
I simply have:
在我的RestController
我只是:
@RequestMapping("/devices/")
public @ResponseBody List<Device> index() {
List<Device> devices = new ArrayList<>();
devices.add(new Device("321421521", ZonedDateTime.now(), 0, 39.89011333, 24.438176666));
return devices;
}
I was expecting the ZonedDateTime
to be formatted according to the ISO format, but instead I am getting a whole JSON dump of the class like this:
我期待ZonedDateTime
根据 ISO 格式对它进行格式化,但是我得到了该类的整个 JSON 转储,如下所示:
"lastUpdated":{"offset":{"totalSeconds":7200,"id":"+02:00","rules":{"fixedOffset":true,"transitionRules":[],"transitions":[]}},"zone":{"id":"Europe/Berlin","rules":{"fixedOffset":false,"transitionRules":[{"month":"MARCH","timeDefinition":"UTC","standardOffset":{"totalSeconds":3600,"id":"+01:00","rules":{"fixedOffset":true,"transitionRules":[],"transitions":[]}},"offsetBefore":{"totalSeconds":3600,"id":"+01:00","rules":{"fixedOffset":true,"transitionRules":[],"transitions":[]}},"offsetAfter":{"totalSeconds":7200,"id":"+02:00", ...
I just have a spring-boot-starter-web
application, using spring-boot-starter-jetty
and excluding spring-boot-starter-tomcat
.
我只有一个spring-boot-starter-web
应用程序,使用spring-boot-starter-jetty
和排除spring-boot-starter-tomcat
.
Why is Hymanson behaving like this in Spring Boot?
为什么Hyman逊在 Spring Boot 中表现如此?
** UPDATE **
** 更新 **
For those looking for a full step by step guide how to solve this I found this after asking the question: http://lewandowski.io/2016/02/formatting-java-time-with-spring-boot-using-json/
对于那些正在寻找如何解决这个问题的完整分步指南的人,我在提出问题后发现了这一点:http: //lewandowski.io/2016/02/formatting-java-time-with-spring-boot-using-json/
采纳答案by vsminkov
There is a library Hymanson-datatype-jsr310. Try it.
有一个库Hymanson-datatype-jsr310。尝试一下。
This library covers new datetime API and includes serializers for ZonedDateTime
too.
这个库涵盖了新的日期时间 API,也包括序列化程序ZonedDateTime
。
All you need is just to add JavaTimeModule
:
您只需要添加JavaTimeModule
:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
UPDATE
更新
To convert datetime to ISO-8601
string you should disable WRITE_DATES_AS_TIMESTAMPS
feature. You can easily do by either overriding ObjectMapper
bean or by using application properties:
要将日期时间转换为ISO-8601
字符串,您应该禁用WRITE_DATES_AS_TIMESTAMPS
功能。您可以通过覆盖ObjectMapper
bean 或使用应用程序属性轻松完成:
spring.Hymanson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
回答by bpawlowski
If you either don't rely on SpringBoot's auto-configuration feature - you don't provide spring.Hymanson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
property into your configuration file - or for whatever reason you create ObjectMapper
instance manually. You can disable this feature programatically as follows:
如果您不依赖 SpringBoot 的自动配置功能 - 您没有spring.Hymanson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
在配置文件中提供属性 - 或者出于任何原因ObjectMapper
手动创建实例。您可以按如下方式以编程方式禁用此功能:
ObjectMapper m = new ObjectMapper();
m.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
this is for Hymanson 2.8.7
这是给Hyman逊的 2.8.7
回答by UltimaWeapon
The answer was already mentioned above but I think it's missing some info. For those looking to parse Java 8 timestamps in many forms (not just ZonedDateTime). You need a recent version of Hymanson-datatype-jsr310
in your POM and have the following module registered:
上面已经提到了答案,但我认为它缺少一些信息。对于那些希望以多种形式(不仅仅是 ZonedDateTime)解析 Java 8 时间戳的人。您需要Hymanson-datatype-jsr310
在 POM 中使用最新版本并注册以下模块:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
To test this code
要测试此代码
@Test
void testSeliarization() throws IOException {
String expectedJson = "{\"parseDate\":\"2018-12-04T18:47:38.927Z\"}";
MyPojo pojo = new MyPojo(ZonedDateTime.parse("2018-12-04T18:47:38.927Z"));
// serialization
assertThat(objectMapper.writeValueAsString(pojo)).isEqualTo(expectedJson);
// deserialization
assertThat(objectMapper.readValue(expectedJson, MyPojo.class)).isEqualTo(pojo);
}
Note that you can configure your object mapper globally in Spring or dropwizard to achieve this. I have not yet found a clean way to do this as an annotation on a field without registering a custom (de)serializer.
请注意,您可以在 Spring 或 dropwizard 中全局配置对象映射器来实现此目的。我还没有找到一种干净的方法来在不注册自定义(反)序列化程序的情况下将其作为字段上的注释。
回答by Somu
For Hymanson 2.10
and above,
对于Hyman逊2.10
及以上,
parent pom.xml
父 pom.xml
<!-- https://github.com/FasterXML/Hymanson-bom -->
<dependencyManagement>
<dependency>
<groupId>com.fasterxml.Hymanson</groupId>
<artifactId>Hymanson-bom</artifactId>
<version>2.10.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>
module pom.xml
模块 pom.xml
<!-- https://github.com/FasterXML/Hymanson-modules-java8 -->
<dependency>
<groupId>com.fasterxml.Hymanson.datatype</groupId>
<artifactId>Hymanson-datatype-jsr310</artifactId>
</dependency>
JsonMapper creation, possibly in your @Configuration
class
JsonMapper 创建,可能在你的@Configuration
课堂上
@Bean
public JsonMapper jsonMapper() {
return JsonMapper.builder()
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.addModule(new JavaTimeModule())
.build();
}
Further reading:
进一步阅读: