如何(联合国)将日期作为杰克逊的时间戳进行编组

And*_*ers 3 json jax-rs jersey jackson java.util.date

我遇到麻烦(联合国)将java.util.Date对象编组到时间戳中.理想情况下,时间戳应采用UTC-0格式,而不是服务器的本地时区.虽然如果需要,我可以很容易地解决这个问题.

注意:我知道这里有几个关于堆栈溢出的类似主题,但是我遇到的每个人都要么过时(关于正在使用的API),要么与将Date对象序列化为字符串有关.

以下是我的POM文件的摘录:

<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>javax.ws.rs-api</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.15</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

样本模型类:

public class PersonJSON {
    private Date birthDate;
}
Run Code Online (Sandbox Code Playgroud)

预期产出(假设出生日期为2015年2月1日00:00:00 UTC-0):

{"birthDate":1422748800000}
Run Code Online (Sandbox Code Playgroud)

当前输出:

{"birthDate":"2015-02-01"}
Run Code Online (Sandbox Code Playgroud)

是否可以解决这个问题(理想情况下使用注释)?

事实证明,错误是由Java.sql.Date到Java.util.Date的隐式转换引起的.转换不会抛出任何异常,并且sql.Date扩展了util.Date,因此逻辑上它应该可以工作,但事实并非如此.解决方案是从Java.sql.Date中提取时间戳,并将其用作Java.util.Date构造函数的输入.

如果您确实想要更改格式,假设您有一个有效的Java.util.Date对象,那么peeskillet列出的方法是正确的.

Pau*_*tha 6

你只需要配置SerializationFeature.WRITE_DATES_AS_TIMESTAMPS就可以了ObjectMapper.从我测试的我不需要配置反序列化,它通过时间戳工作得很好.

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {

    private final ObjectMapper mapper;

    public ObjectMapperContextResolver() {
        mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) { return mapper; }

}
Run Code Online (Sandbox Code Playgroud)

至于通过每个字段的注释设置此功能,我不知道如何在没有编写自定义序列化器的情况下如何使用Jackson(但我不怀疑是否还有其他方法).您始终可以使用Jackson提供程序附带的JAXB注释支持.只需编写一个XmlAdapter并注释该字段即可@XmlJavaTypeAdatper(YourDateAdapter.class).这是一个例子


UPDATE

完整的例子.

必需的依赖项

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>2.15</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.15</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

测试(您需要从上面注册上下文解析器)

import java.util.Date;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import jersey.stackoverflow.provider.ObjectMapperContextResolver;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

public class ObjectMapperTest extends JerseyTest {

    public static class Person {
        public Date birthDate;
    }

    @Path("/person") @Produces(MediaType.APPLICATION_JSON)
    public static class PersonResource {
        @GET 
        public Response getPerson() {
            Person person = new Person();
            person.birthDate = new Date();
            return Response.ok(person).build();
        }
    }

    @Override
    public Application configure() {
        return new ResourceConfig(PersonResource.class,
                                  ObjectMapperContextResolver.class);
    }

    @Test
    public void test() {
        String personJson = target("person").request().get(String.class);
        System.out.println(personJson);
    }
}
Run Code Online (Sandbox Code Playgroud)

结果: {"birthDate":1423738762437}


更新2

我不认为这个答案是正确的.杰克逊似乎默认将其序列化为时间戳.如果我们不想要时间戳,那么我们将上面的配置设置为false.但这仍然没有回答OP的问题.不确定是什么问题.


Bri*_*ace 5

我也遇到了这个问题。在我的情况下,Hibernate ORM 将java.util.Date实体属性加载为java.sql.Date对象,这些对象没有像我预期的那样序列化为时间戳(这是 jackson 在序列化java.util.Date对象时采用的默认序列化策略)。

我的解决方法是明确指示java.sql.Date对象使用 jackson 的 stockcom.fasterxml.jackson.databind.ser.std.DateSerializer类,就像它用于java.util.Date对象一样:

private Client buildClient() {
  return ClientBuilder.newBuilder()
    .register(getJacksonJsonProvider())
    .build();
}

private JacksonJsonProvider getJacksonJsonProvider() {
  JacksonJsonProvider jjp = new JacksonJaxbJsonProvider();
  jjp.setMapper(getJsonObjectMapper());
  return jjp;
}

private ObjectMapper getJsonObjectMapper() {
   ObjectMapper mapper = new ObjectMapper();
   mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   SimpleModule module = new SimpleModule();
   module.addSerializer(java.sql.Date.class, new DateSerializer()); // <-- My Fix
   mapper.registerModule(module);
   return mapper;
}
Run Code Online (Sandbox Code Playgroud)