java - Jersey 解析 Java 8 日期时间

标签 java datetime jersey jax-rs java-8

这是我的用户类,我要在我的数据库中保存符合 ISO 标准的日期时间。

public class User  {

    @Id
    private String id;

    private String email;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private LocalDateTime loginDate;

 }

这是我的 Jersey Controller :

@POST
@Consumes("application/json")
@Produces("application/json")

public Response create(  User user) {

    Map<Object, Object> apiResponse = new HashMap<Object, Object>();
    Map<Object, Object> response  = new HashMap<Object, Object>();


    user = (User) userService.create(user);

}

我怎样才能在 Jersey 中使用像这样的日期时间格式?是否可以发送数据时间 String 并自动创建 Java 8 日期时间对象?

{        
    "email" : "imz.mrz@gmail.com"
    "loginDate" : "2015-04-17T06:06:51.465Z"
} 
#

更新:

我用的是Spring boot jersey,还有其他的jsr包

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-jersey</artifactId>
 </dependency>

所以我删除了除 spring-boot-jersey 包之外的所有包。 将此注释用于 LocalDateTime

  @JsonDeserialize(using =  LocalDateTimeDeserializer.class)

这样我就可以使用 ISODate 并将 ISODate() 保存到 mongodb 并生成完整格式的 mongodb LocalDateTime 到前端。

问题已解决。

最佳答案

我看到了几个选项...

选项 1:

假设您有 JAXB 注释支持,Jackson 作为 JSON 提供者...

您可以使用 XmlAdapter。例如

public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {

    @Override
    public LocalDateTime unmarshal(String dateString) throws Exception {
        Instant instant = Instant.parse(dateString);
        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return dateTime;
    }

    @Override
    public String marshal(LocalDateTime dateTime) throws Exception {
        Instant instant = dateTime.toInstant(ZoneOffset.UTC);
        return DateTimeFormatter.ISO_INSTANT.format(instant);
    }
}

请参阅 Instant API了解更多信息。

然后你可以只用适配器注释字段/属性

@XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
private LocalDateTime loginDate;

您还可以在包级别声明注释,这样包中的所有使用都将使用适配器,而无需注释。您在包内名为 package-info.java 的文件中执行此操作

@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(type = LocalDateTime.class, 
                        value = LocalDateTimeAdapter.class)
})
package thepackage.of.the.models;

import java.time.LocalDateTime;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

选项 2:

直接使用 Jackson API。意思是,使用 JsonDeserializerJsonSerializer。例如

public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

    @Override
    public LocalDateTime deserialize(JsonParser jp, 
            DeserializationContext dc) throws IOException, JsonProcessingException {
        ObjectCodec codec = jp.getCodec();
        TextNode node = (TextNode)codec.readTree(jp);
        String dateString = node.textValue();
        Instant instant = Instant.parse(dateString);
        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return dateTime;
    } 
}

public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

    @Override
    public void serialize(LocalDateTime dateTime, JsonGenerator jg, 
            SerializerProvider sp) throws IOException, JsonProcessingException {
        Instant instant = dateTime.toInstant(ZoneOffset.UTC);
        jg.writeString(DateTimeFormatter.ISO_INSTANT.format(instant));
    } 
}

您可以在字段/属性级别应用它

@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime loginDate; 

或者在 ObjectMapper 级别(这样你就不需要在任何地方都进行注释)

@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {

    final ObjectMapper mapper = new ObjectMapper();

    public ObjectMapperContextResolver() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        mapper.registerModule(module);
        // add JAXB annotation support if required
        mapper.registerModule(new JaxbAnnotationModule());
    }

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

基本上发生的事情是,用于汇总/编码的 MessageBodyWriter/MessageBodyReader 将调用 getContext 方法来获取 对象映射器

注意:

  • 上述解决方案将从 2007-12-03T10:15:30.00Z 格式解析,如 Instant.parse 中所述, 并将序列化为相同的格式,如 DateTimeFormatter.ISO_INSTANT 中所述

  • 以上内容还假设您使用 Jackson 作为序列化器。我使用以下依赖项(使用 Jersey 2.16)进行测试

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.16</version>
    </dependency>
    

    依赖项使用 JacksonJaxbJsonProvider 来支持 JAXB 注释。如果您使用的是较低版本的 Jersey,例如 1.x,如果您启用了 POJO 映射功能,jersey-json 依赖项应该提供 JAXB 注释支持。或者对于 Jersey 1.x,如果你想使用 Jackson 2,你可以使用这个依赖项

    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.4.0</version>
    </dependency>
    

    这实际上是 jersey-media-json-jackson 使用的。因此,您可以显式注册 JacksonJaxbJsonProvider,或添加 Jackson 包 (com.fasterxml.jackson.jaxrs.json) 以列出要扫描的包


更新

另请参阅:

关于java - Jersey 解析 Java 8 日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29736660/

相关文章:

spring - jersey-spring3 实例化 Spring 管理的 bean (null!)

java - 使用Oracle日期字段中的cachedrowset时如何获取完整的日期和时间数据

Java - 将小时( double )转换为分钟(整数),反之亦然

java - 使用 Jersey deps 将应用程序打包到 jar 中时出现问题

mysql - 日期时间值不正确 : '0000-00-00 00:00:00' for column

c# - 适用于任何文化的 DateTime.TryParse

java - 更新 tomcat 库中的 jar

java - write (byte[] b) 大字节数组的优化用法

java - 组件需要名为 'userService' 的 bean,但无法找到

java - 我是 Android 中 SQLite 的新手,这是我的功能,但没什么用