在JAX-RS响应中使用ISO-8601日期

时间:2014-05-19 05:08:53

标签: java json glassfish jax-rs iso8601

我在GlassFish 4上使用Java EE 7构建RESTful Web服务。在序列化包含java.util.Date个对象的POJO时,不包括时区信息。

如何自定义对象序列化,以便java.util.Date包含时区信息?

例如,而不是:

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

我反而喜欢这样:

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

服务器的时区为GMT + 09:30。

1 个答案:

答案 0 :(得分:6)

这是由MOXy中的bug引起的,它是GlassFish中JAX-RS的默认JSON(反)序列化器。

解决方法是将JSON提供程序切换到Jackson。

第一步是将这些依赖项添加到构建中:

<!-- Provides JacksonFeature -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.8</version>
    <scope>provided</scope>
</dependency>

<!-- Provides ObjectMapper and SerializationConfig -->
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
    <type>jar</type>
</dependency>

下一步,添加JacksonFeature作为提供程序,将MOXy替换为JSON序列化程序:

@ApplicationPath("/api/1")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        addRestResourceClasses(resources);

        // Add Jackson feature.
        resources.add(org.glassfish.jersey.jackson.JacksonFeature.class);

        return resources;
    }

    private void addRestResourceClasses(Set<Class<?>> resources) {
        // JAX-RS resource classes added here - maintained by NetBeans.
    }
}

Jackson的默认行为是以纪元形式出现的毫秒数表示java.util.Date。要将其更改为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<ObjectMapper> {

    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();
}