如何让JAX-RS将Java 8 LocalDateTime属性作为JavaScript样式的日期字符串返回?

Joe*_*oe7 9 java json jax-rs java-8 java-time

我使用JAX-RS方法注释创建了一个RESTful Web服务:

@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public MyThing test()
{
    MyThing myObject = new MyThing(LocalDateTime.now());
    return myObject;
}
Run Code Online (Sandbox Code Playgroud)

这很好用,但我想调整一件事:如果返回的Java对象包含新Java 8 LocalDateTime类型的属性,则表示为JSON对象:

{"myDateTimeProperty":{"hour":14,"minute":32,"second":39,"year":2014,"month":"NOVEMBER","dayOfMonth":6,"dayOfWeek":"THURSDAY","dayOfYear":310,"monthValue":11,"nano":0,"chronology":{"calendarType":"iso8601","id":"ISO"}},...}
Run Code Online (Sandbox Code Playgroud)

如何告诉JAX-RS返回一个JavaScript Date.toJSON() - 样式字符串

{"myDateTimeProperty":"2014-11-07T15:06:36.545Z",...}
Run Code Online (Sandbox Code Playgroud)

代替?

Pau*_*tha 8

注意:请参阅下面的更新

我以前从未使用LocalDateTime过,所以我决定做一些测试.以下是我的发现:

  • Jersy 2.13和这个提供商(没有额外配置的盒子)

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    
    Run Code Online (Sandbox Code Playgroud)
  • Jersey 2.13使用此提供程序(支持JAXB注释 - 依赖于jackson-module-jaxb-annotations),带有自定义适配器

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    
    public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
        @Override
        public LocalDateTime unmarshal(String s) throws Exception {
            return LocalDateTime.parse(s);
        }
        @Override
        public String marshal(LocalDateTime dateTime) throws Exception {
            return dateTime.toString();
        }   
    }
    
    // Getter for model class
    @XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
    public LocalDateTime getDateTime() {
        return dateTime;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用此提供程序的Resteasy 3.0.9(也支持JAXB注释 - 依赖于jackson-module-jaxb-annotations),使用自定义适配器(参见上文)

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>${resteasy.version}</version>
    </dependency>
    
    Run Code Online (Sandbox Code Playgroud)
  • Resteasy和Jersey都有这种依赖性(没有自定义配置也没有用,与后两个相同 - 带适配器)

    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.4.0</version>
    </dependency>
    
    Run Code Online (Sandbox Code Playgroud)

    我们需要确保注册 JacksonJaxbJsonProvider


所以我想似乎任何使用Jackson的提供商都没有给你带来deisred结果,没有一些自定义配置,无论是通过适配器(如上所示)还是其他一些自定义配置.该jersey-media-moxy供应商不使用杰克逊.


UPDATE

在大多数情况下,上述信息不正确.

  • 莫西 并不默认工作.它的工作原理进行序列化通过简单地调用toString(),这可能会或可能不是你想要的是,它将无法正常工作时, -serializing.如果您使用MOXy,直到它支持Java8时间,您将需要使用XMLAdapter

  • 杰克逊你需要配置它的Java8时间支持.Jersey和RESTEasy都是这种情况.

  • 太棒了,我现在将适配器作为包级注释包含在内,这对我来说很有用.值得注意的是,包级别注释必须包含在单独的package-info.java文件中,而不是任何特定的类文件中. (2认同)

ass*_*ias 6

我不记得为什么我这样做的具体细节,但我得到了以下依赖项:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.4.2</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-jsr310</artifactId>
  <version>2.4.2</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

以下提供者:

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
  private static final ObjectMapper om = init();

  @Override public ObjectMapper getContext(Class<?> objectType) {
    return om;
  }

  private static ObjectMapper init() {
    ObjectMapper om = new ObjectMapper();
    om.registerModule(new JavaTimeModule());
    return om;
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您还可以使用以下标志:

om.configure(WRITE_DATES_AS_TIMESTAMPS, true/false);
Run Code Online (Sandbox Code Playgroud)

(实际的课程中有更多的东西,但我相信这与这个答案无关).