Java 使用 Jackson JSR310 模块反序列化 LocalDateTime

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29571587/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:14:43  来源:igfitidea点击:

Deserializing LocalDateTime with Hymanson JSR310 module

javaHymansonjava-timejsr310

提问by Mekswoll

I'm using the library described the Hymanson Datatype JSR310 pagebut I'm still having difficulty getting it to work.

我正在使用描述Hymanson Datatype JSR310 页面的库但我仍然难以让它工作。

I have configured the following bean:

我已经配置了以下bean:

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JSR310Module());
    return mapper;
}

When I call my REST API the date format output is yyyy-MM-dd'T'HH:ss.SSSSSS, e.g. 2015-04-11T00:10:38.905847. This gets handled by my AngularJS code just fine.

当我调用我的 REST API 时,日期格式输出是yyyy-MM-dd'T'HH:ss.SSSSSS,例如2015-04-11T00:10:38.905847. 这由我的 AngularJS 代码处理得很好。

When I want to submit something to the REST API the date is posted as yyyy-MM-dd'T'HH:mm:ss.SSS'Z', e.g. 2015-04-09T08:30:00.000Z

当我想向 REST API 提交某些内容时,日期发布为yyyy-MM-dd'T'HH:mm:ss.SSS'Z',例如2015-04-09T08:30:00.000Z

Hymanson keeps complaining about the 'Z' at the end. If I look at the LocalDateTimeDeserializerin the documentation it uses the DateTimeFormatter.ISO_LOCAL_DATE_TIMEwhich boils to ISO_LOCAL_DATE'T'ISO_LOCAL_TIMEand it mentions it has no override zone.

Hyman逊最后一直抱怨“Z”。如果我查看LocalDateTimeDeserializer文档中的 ,它会使用DateTimeFormatter.ISO_LOCAL_DATE_TIME沸腾到的 ,ISO_LOCAL_DATE'T'ISO_LOCAL_TIME并且它提到它没有覆盖区域。

So I figured I should set the DateFormaton the ObjectMapperI'm creating:

所以我想我应该设置DateFormatObjectMapper我创建:

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JSR310Module());
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
    return mapper;
}

But this does nothing. I changed it to something simple like yyyy-MM-ddbut the serialized date remained in the previous format and the deserialization isn't affected either.

但这没有任何作用。我把它改成简单的东西,yyyy-MM-dd但序列化日期保持在以前的格式,反序列化也不受影响。

What am I doing wrong here to get this to work? The date format in my JavaScript code is, as far as I know the ISO 8601 format...

我在这里做错了什么才能让它发挥作用?据我所知,我的 JavaScript 代码中的日期格式是 ISO 8601 格式...

采纳答案by user1299153

It's not necessary to write your own serializer. It's enough use the default one, but making an instance with another format (the time_zoneone) so that the exceeding part is just cut:

没有必要编写自己的序列化程序。使用默认的就足够了,但是用另一种格式(那个time_zone)制作一个实例,这样超出的部分就被剪掉了:

new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)

In my case I've got a contextResolverlike this to achieve at configuration level:

就我而言,我contextResolver在配置级别有这样的实现:

@Service 
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper mapper;

    public ObjectMapperContextResolver() {
        mapper = new ObjectMapper();
        JavaTimeModule javaTimeModule=new JavaTimeModule();
        // Hack time module to allow 'Z' at the end of string (i.e. javascript json's) 
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
        mapper.registerModule(javaTimeModule);
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}

回答by Alexey Gavrilov

For now LocalDateTimeDeserializerdoes not seem to respect the date format set for the object mapper.

现在LocalDateTimeDeserializer似乎不尊重为对象映射器设置的日期格式。

To make it work you can override LocalDateTimeDeserializeror switch to use ZoneDateTimewhich handles the 'Z' char at the end.

为了使其工作,您可以覆盖LocalDateTimeDeserializer或切换到使用ZoneDateTime哪个处理末尾的 'Z' 字符。

Here is an example:

下面是一个例子:

public class Java8DateFormat {
    public static void main(String[] args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JSR310Module());
        // mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));

        final String date = mapper.writeValueAsString(new Date());
        System.out.println(date);
        System.out.println(mapper.readValue(date, ZonedDateTime.class));
    }
}

Output:

输出:

"2015-04-11T18:24:47.815Z"
2015-04-11T18:24:47.815Z[GMT]

回答by hariprasad

Hibernate 4, Spring 4 - REST WS, Client - Spring Boot 1.5.2. In my case I used in Entity ZonedDateTimeclass to map Timestampin database. Hibernate as well as Spring Boot REST works fine. I must only add libraries into pomfile:

Hibernate 4、Spring 4 - REST WS、客户端 - Spring Boot 1.5.2。在我的例子中,我在 Entity ZonedDateTime类中使用来映射数据库中的时间戳。Hibernate 以及 Spring Boot REST 工作正常。我必须只将库添加到pom文件中:

    <!-- https://mvnrepository.com/artifact/com.fasterxml.Hymanson.core/Hymanson-annotations -->
    <dependency>
        <groupId>com.fasterxml.Hymanson.core</groupId>
        <artifactId>Hymanson-annotations</artifactId>
        <version>${Hymanson.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.fasterxml.Hymanson.datatype/Hymanson-datatype-jsr310 -->
    <dependency>
        <groupId>com.fasterxml.Hymanson.datatype</groupId>
        <artifactId>Hymanson-datatype-jsr310</artifactId>
        <version>${Hymanson.version}</version>
    </dependency>

So I suppose, that converter is implemented inside Spring for LocalDateTimeas well.The Hymanson.versionis the latest one.

所以我想,是转换器内部弹簧实现了LocalDateTime为well.The Hymanson.version是最新的一个。