有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

json如何让JAXRS将Java8LocalDateTime属性作为JavaScriptstyle日期字符串返回?

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

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

这可以很好地工作,但我想调整一件事:如果返回的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"}},...}

我如何告诉JAX-RS返回JavaScript日期。toJSON()-类似字符串的样式

{"myDateTimeProperty":"2014-11-07T15:06:36.545Z",...}

相反


共 (3) 个答案

  1. # 1 楼答案

    注:见下文更新

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

    • Jersy 2.13和这个提供程序(在没有额外配置的情况下计算出盒子)

      <dependency>
          <groupId>org.glassfish.jersey.media</groupId>
          <artifactId>jersey-media-moxy</artifactId>
          <version>${jersey.version}</version>
      </dependency>
      
    • Jersey 2.13(支持JAXB注释——对jackson模块JAXB注释的依赖),带有自定义适配器

      <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;
      }
      
    • Resteasy 3.0.9与此提供程序(还支持JAXB注释——对jackson模块JAXB注释的依赖),以及自定义适配器(见上文)

      <dependency>
          <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-jackson2-provider</artifactId>
          <version>${resteasy.version}</version>
      </dependency>
      
    • Resteasy和Jersey都有这个依赖项(没有自定义配置也不能工作,和前两个一样——有适配器)

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

      我们需要确保注册JacksonJaxbJsonProvider


    所以我猜,似乎任何使用Jackson的提供者,在没有一些自定义配置的情况下,都不会给你deisred结果,无论是通过适配器(如上所示)还是其他自定义配置。{}提供程序不使用Jackson


    更新

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

    • 默认情况下,MOXy不起作用。它通过简单地调用toString()来实现序列化,这可能是您想要的,也可能不是您想要的,当de序列化时,它将不起作用。如果您使用的是MOXy,在它支持Java8 time之前,您需要use an XMLAdapter

    • 杰克逊你需要configure its Java8 time support。Jersey和RESTEasy都是这样

  2. # 2 楼答案

    更新:使用:<version>2.4.2</version>

    当我尝试上述方法时:

    Caused by: java.lang.NoSuchMethodError: com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value;

    我得到以下错误。有什么想法吗

    <jackson.version>2.8.0</jackson.version>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-jsr310</artifactId>
                <version>${jackson.version}</version>
    

    package com.jobs.spring.configuration;
    
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.ext.ContextResolver;
    import javax.ws.rs.ext.Provider;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
    
    @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 JSR310Module());
            return om;
        }
    }
    

    在2.8.0中,由于JSR310Module()被弃用,因此也尝试了以下方法

    om.registerModule(new JavaTimeModule());
    
  3. # 3 楼答案

    我不记得我为什么这么做的确切细节,但我通过以下依赖项实现了它:

    <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>
    

    以及以下提供商:

    @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;
      }
    }
    

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

    om.configure(WRITE_DATES_AS_TIMESTAMPS, true/false);
    

    (实际课堂上有更多内容,但我相信这与这个答案无关)