Use datas ISO-8601 nas respostas JAX-RS

Estou construindo serviços Web RESTful usando o Java EE 7 no GlassFish 4. Ao serializar POJOs contendo objects java.util.Date , as informações de fuso horário não são incluídas.

Como posso personalizar a serialização de objects para que java.util.Date s tenha informações de fuso horário incluídas?

Por exemplo, em vez disso:

 { "id": 1234, "foo": "2014-05-19T13:53:49.392" } 

Eu preferiria assim:

 { "id": 1234, "foo": "2014-05-19T13:53:49.392+09:30" } 

Onde o fuso horário do servidor é GMT + 09:30.

Isso é causado por um bug no MOXy, que é o serializador JSON (de) padrão para o JAX-RS no GlassFish.

A solução alternativa é mudar os provedores de JSON para Jackson.

O primeiro passo é adicionar essas dependencies à construção:

   org.glassfish.jersey.media jersey-media-json-jackson 2.8 provided    org.codehaus.jackson jackson-mapper-asl 1.9.13 jar  

Na próxima etapa, adicione JacksonFeature como um provedor, que replaceá o MOXy como o serializador JSON:

 @ApplicationPath("/api/1") public class ApplicationConfig extends Application { @Override public Set> getClasses() { Set> resources = new java.util.HashSet<>(); addRestResourceClasses(resources); // Add Jackson feature. resources.add(org.glassfish.jersey.jackson.JacksonFeature.class); return resources; } private void addRestResourceClasses(Set> resources) { // JAX-RS resource classs added here - maintained by NetBeans. } } 

O comportamento padrão de Jackson é representar java.util.Date em seus milissegundos desde a forma de época. Para mudar isso para ISO-8601:

 import java.text.SimpleDateFormat; import java.util.TimeZone; import javax.ws.rs.Produces; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; @Provider @Produces("application/json") public class JacksonConfigurator implements ContextResolver { public JacksonConfigurator() { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); mapper.setDateFormat(dateFormat); mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); } @Override public ObjectMapper getContext(Class clazz) { return mapper; } private final ObjectMapper mapper = new ObjectMapper(); }