How can I get JAX-RS to return the Java 8 LocalDateTime property as a JavaScript style date string?

I created a RESTful web service using JAX-RS annotations:

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

This works well, but I would like to set up one thing: if the returned Java object contains a property of the new Java 8 LocalDateTime type, it appears as a JSON object:

 {"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 string Date.toJSON (), for example

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

instead

+6
source share
3 answers

Note: see UPDATE below

I have never used LocalDateTime before, so I decided to do some testing. Here are my findings:

  • Jersy 2.13 and this provider (displays a window without additional 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 JAXB annotation support - jackson-module-jaxb annotation dependency), with a custom adapter

     <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 with this provider (also supports JAXB annotation - jackson-module-jaxb annotation dependency), with a custom adapter (see above)

     <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson2-provider</artifactId> <version>${resteasy.version}</version> </dependency> 
  • Both Resteasy and Jersey with this dependency (also did not work without a custom configuration, just like the last two with an adapter)

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

    We need to register JacksonJaxbJsonProvider


So, it seems that any provider using Jackson does not give you the final result without any custom configuration, either through the adapter (as seen above) or some other custom configuration. The jersey-media-moxy does not use Jackson.


UPDATE

For the most part, the above information is incorrect.

  • MOXy does not work by default. It works for serialization by simply calling toString() , which may or may not be what you want, and it will not work on de-serialization. If you use MOXy while it does not support Java8 time, you need to use the XMLAdapter

  • Jackson you will need to configure your Java8 time support . This applies to both Jersey and RESTEasy.

+7
source

I don’t remember the details about why I did this, but I got it working with the following dependencies:

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

And the provider below:

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

Please note that you can also play with the following flag:

 om.configure(WRITE_DATES_AS_TIMESTAMPS, true/false); 

(the actual class has more things, but I believe this is not relevant to this answer).

+5
source

UPDATED : works with: <version>2.4.2</version>

When I try the above:

Called: java.lang.NoSuchMethodError: com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides (Lcom / fasterxml / Jackson / DataBind / SerializerProvider; Lcom / fasterxml / Bexind / Beanml Jax ) Lcom / fasterxml / jackson / annotations / JsonFormat $ Value;

I get the following error. Any ideas 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; } } 

Also tried the following: JSR310Module() depreciates at 2.8.0

 om.registerModule(new JavaTimeModule()); 
0
source

Source: https://habr.com/ru/post/977884/


All Articles