如何让 JAX-RS 将 Java 8 LocalDateTime 属性作为 JavaScript 样式的日期字符串返回?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26804941/
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
How can I have JAX-RS return a Java 8 LocalDateTime property as a JavaScript-style Date String?
提问by Joe7
I created a RESTful web service using JAX-RS method annotations:
我使用 JAX-RS 方法注释创建了一个 RESTful Web 服务:
@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public MyThing test()
{
MyThing myObject = new MyThing(LocalDateTime.now());
return myObject;
}
This works nicely, but I'd like to adjust one thing: If the returned Java object contains a property of the new Java 8 LocalDateTime type, it is represented as a JSON object:
这很好用,但我想调整一件事:如果返回的 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"}},...}
How can I tell JAX-RS to return a JavaScript Date.toJSON()-style String like
我如何告诉 JAX-RS 返回一个 JavaScript Date.toJSON()-style String like
{"myDateTimeProperty":"2014-11-07T15:06:36.545Z",...}
instead?
反而?
采纳答案by Paul Samsotha
Note: See UPDATE below
注意:请参阅下面的更新
I've never use LocalDateTime
before, so I decided to do some testing. Here are my findings:
我以前从未使用LocalDateTime
过,所以我决定做一些测试。以下是我的发现:
Jersy 2.13 and this provider (works out the box with no extra configuration)
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> <version>${jersey.version}</version> </dependency>
Jersey 2.13 with this provider (has support for JAXB annotation - dependency on Hymanson-module-jaxb-annotations), with custom adapter
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-Hymanson</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 with this provider, (also has support for JAXB annotation - dependency on Hymanson-module-jaxb-annotations), with custom adapter (See above)
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-Hymanson2-provider</artifactId> <version>${resteasy.version}</version> </dependency>
Both Resteasy and Jersey with this dependency (also did not work without custom config, same as last two - with adapter)
<dependency> <groupId>com.fasterxml.Hymanson.jaxrs</groupId> <artifactId>Hymanson-jaxrs-json-provider</artifactId> <version>2.4.0</version> </dependency>
We need to make sure to register the
HymansonJaxbJsonProvider
Jersy 2.13 和这个提供者(无需额外配置即可使用)
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> <version>${jersey.version}</version> </dependency>
带有此提供程序的 Jersey 2.13(支持 JAXB 注释 - 依赖于 Hymanson-module-jaxb-annotations),带有自定义适配器
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-Hymanson</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 注释 - 依赖于 Hymanson-module-jaxb-annotations),带有自定义适配器(见上文)
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-Hymanson2-provider</artifactId> <version>${resteasy.version}</version> </dependency>
Resteasy 和 Jersey 都具有这种依赖性(如果没有自定义配置也无法工作,与前两个相同 - 使用适配器)
<dependency> <groupId>com.fasterxml.Hymanson.jaxrs</groupId> <artifactId>Hymanson-jaxrs-json-provider</artifactId> <version>2.4.0</version> </dependency>
我们需要确保注册
HymansonJaxbJsonProvider
So I guess it seems that any provider that uses Hymanson, does not give you the deisred result, without some custom configuration, whether its through an adapter (as seen above) or some other custom configuration. The jersey-media-moxy
provider doesn't use Hymanson.
所以我想似乎任何使用 Hymanson 的提供者都不会给你想要的结果,没有一些自定义配置,无论是通过适配器(如上所示)还是其他一些自定义配置。该jersey-media-moxy
供应商不使用Hyman逊。
UPDATE
更新
For the most part, the information above is incorrect.
在大多数情况下,上述信息是不正确的。
MOXydoes notwork by default. It works for serialization by simply calling
toString()
, which may or may not be what you want, and it won't work when de-serializing. If you are using MOXy, until it supports Java8 time, you will need to use an XMLAdapterHymansonyou will need to configure its Java8 time support. This is the case with both Jersey and RESTEasy.
MOXy默认不工作。它的工作原理进行序列化通过简单地调用
toString()
,这可能会或可能不是你想要的是,它将无法正常工作时,德-serializing。如果您使用的是 MOXy,在它支持 Java8 之前,您将需要使用 XMLAdapterHymanson你需要配置它的 Java8 时间支持。Jersey 和 RESTEasy 都是这种情况。
回答by assylias
I don't remember the exact details of why I did this but I got it working with the following dependencies:
我不记得我为什么这样做的确切细节,但我让它与以下依赖项一起工作:
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-databind</artifactId>
<version>2.4.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.Hymanson.datatype</groupId>
<artifactId>Hymanson-datatype-jsr310</artifactId>
<version>2.4.2</version>
</dependency>
And the provider below:
以及下面的提供者:
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class HymansonContextResolver 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;
}
}
Note that you can also play with the following flag:
请注意,您还可以使用以下标志:
om.configure(WRITE_DATES_AS_TIMESTAMPS, true/false);
(the actual class has more stuff in it but I believe it is irrelevant to this answer).
(实际的课程中有更多的东西,但我相信它与这个答案无关)。
回答by Richard
UPDATED: works with: <version>2.4.2</version>
更新:适用于:<version>2.4.2</version>
When I try the above:
当我尝试上述操作时:
Caused by: java.lang.NoSuchMethodError: com.fasterxml.Hymanson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/Hymanson/databind/SerializerProvider;Lcom/fasterxml/Hymanson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/Hymanson/annotation/JsonFormat$Value;
引起:java.lang.NoSuchMethodError: com.fasterxml.Hymanson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/Hymanson/databind/SerializerProvider;Lcom/fasterxml/Hymanson/databind/BeanProperty;Ljava/lang/Class ;)Lcom/fasterxml/Hymanson/annotation/JsonFormat$Value;
I get the following error. Any ideas plse?
我收到以下错误。有什么想法吗?
<Hymanson.version>2.8.0</Hymanson.version>
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-annotations</artifactId>
<version>${Hymanson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-databind</artifactId>
<version>${Hymanson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-core</artifactId>
<version>${Hymanson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.Hymanson.datatype</groupId>
<artifactId>Hymanson-datatype-jsr310</artifactId>
<version>${Hymanson.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.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.datatype.jsr310.JSR310Module;
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class HymansonContextResolver 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;
}
}
Also tried with the following as JSR310Module()
is deprecicated in 2.8.0
还尝试了以下内容,因为JSR310Module()
在 2.8.0 中已弃用
om.registerModule(new JavaTimeModule());