Joe7 Joe7 - 4 months ago 132
JSON Question

How can I have JAX-RS return a Java 8 LocalDateTime property as a JavaScript-style Date String?

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

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

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

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


instead?

Answer

I've never use LocalDateTime before, so I decided to do some testing. Here are my findings:

  • 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 jackson-module-jaxb-annotations), with 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 has support for JAXB annotation - dependency on jackson-module-jaxb-annotations), with 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 custom config, same as last two - with adapter)

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

    We need to make sure to register the JacksonJaxbJsonProvider


So I guess it seems that any provider that uses Jackson, 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 Jackson.


Comments