Как я могу вернуть 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());