Как я могу вернуть JAX-RS свойство Java 8 LocalDateTime в качестве строки даты в стиле JavaScript?
Я создал веб-службу RESTful, используя аннотации метода JAX-RS:
@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 ответов
Примечание: см. обновление ниже
Я никогда не использую LocalDateTime
раньше, поэтому я решил сделать некоторые испытания. Вот мои выводы:
-
Jersy 2.13 и этот поставщик (работает в коробке без дополнительной конфигурации)
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> <version>${jersey.version}</version> </dependency>
-
Джерси 2.13 с этим поставщиком (имеет поддержку аннотации JAXB - зависимость от jackson-module-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-module-JAXB-annotations), с пользовательским адаптером (см. выше)
<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
поэтому я думаю, кажется, что любой провайдер, который использует Джексона, не дайте вам результат deisred, без некоторой пользовательской конфигурации, будь то через адаптер (как показано выше) или какую-либо другую пользовательскую конфигурацию. The jersey-media-moxy
провайдер не использует Джексон.
обновление
по большей части, информация выше неверна.
бренда не работать по умолчанию. Он работает для сериализации, просто вызывая
toString()
, который может или не может быть то, что вы хотите, и это не сработает, когда de-сериализации. Если вы используете MOXy, пока он не поддерживает время Java8, вам нужно будет используйте XMLAdapterДжексон вам понадобится настройте поддержку времени Java8. Это относится как к Джерси, так и к RESTEasy.
Я не помню точных деталей, почему я это сделал, но я получил его работу со следующими зависимостями:
<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);
(фактический класс имеет больше вещей в нем, но я считаю, что это не имеет никакого отношения к этому ответу).
обновлено: работает с: <version>2.4.2</version>
когда я попробую выше:
вызвано: java.ленг.NoSuchMethodError: com.fasterxml.Джексон.тип данных.jsr310.серийный.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value;
я получаю следующую ошибку. Любая идея plse?
<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;
}
}
также попытался со следующим as JSR310Module()
это deprecicated в 2.8.0
om.registerModule(new JavaTimeModule());