当前位置: 首页 > 知识库问答 >
问题:

我如何(取消)将日期标记为杰克逊的时间戳

章哲茂
2023-03-14

我在整理java时遇到问题。util。将日期对象转换为时间戳。理想情况下,时间戳应为UTC-0格式,而不是服务器的本地时区。虽然如果需要的话,我可以很容易地解决这个问题。

注意:我知道这里有几个关于堆栈溢出的类似主题,但我遇到的每个人要么已经过时(就使用的API而言),要么都与将日期对象序列化为字符串有关。

这是我的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>

示例模型类:

public class PersonJSON {
    private Date birthDate;
}

预期产出(假设出生日期为2015 00:00:002月1日):

{"birthDate":1422748800000}

电流输出:

{"birthDate":"2015-02-01"}

是否可以修复此问题(理想情况下使用注释)?

解决方案

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

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

共有2个答案

梁丘安晏
2023-03-14

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

我的修复方法是显式地指导java。sql。日期对象使用jackson的股票。fasterxml。杰克逊。数据绑定。序列号。std.DateSerializer类,就像它用于java一样。util。日期对象:

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;
}
陆宝
2023-03-14

您只需要配置序列化功能。在对象映射器上写入\u DATES\u作为\u时间戳。根据我的测试,我不需要配置反序列化,通过时间戳可以很好地工作。

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

}

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

完整的示例。

必需的依赖项

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

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

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

结果:<代码>{“生日”:1423738762437}

我认为这个答案不正确。杰克逊似乎已经在默认情况下序列化为时间戳。如果我们不需要时间戳,那么我们会将上述配置设置为false。但这仍然不能回答OPs的问题。不确定是什么问题。

 类似资料:
  • 我对jackson进行了配置,以便在和时给出一个简单的字符串表示。这可以在序列化过程中找到,例如,当我在REST API上获得数据时。 但反过来就不行了。当我试图将数据发送到服务器,并且应该将JSON解析为java对象时,会引发此异常: 很抱歉没有提到我在单元测试中。 TestClass:

  • 问题内容: 我有一个带有时间戳属性的模型: 时间戳的格式如下: 无法解析此: com.fasterxml.jackson.databind.exc.InvalidFormatException:无法从字符串“ 2017-09-17 13:45:42.710576 + 02” 反序列化类型的值:文本“ 2017-09-17 13:45:42.710576 + 02”可能不能在索引10处解析 我怎样才

  • 我试图在Jackson的spring boot应用程序中从JSON获取日期字段。JSONFormat如下所示: 它在大多数情况下都能正常工作,但当我通过2017-0526时,它会自动将其转换为2018年5月10日。 如果日期不是yyyyMMdd格式或包含减号,我想引发异常。我试图查看堆栈溢出和Jackson文档,但找不到任何东西。 为什么JsonFormat接受负日期? 对此是否有任何解决方法,以

  • 问题内容: 我想将日期从Twitter反序列化为。我的程序在反序列化领域失败。 我的网域课程 我的解析方法 两项测试均失败,并出现java.time.ZonedDateTime 错误。 我已经检查了关于Stackoverflow的类似问题,我的格式看起来正确。 我做错了吗? 解决了 问题出在地区。添加确切的区域设置后,测试开始通过。 对于 用于测试 问题答案: 尝试在您的媒体资源上添加此注释

  • 我想将Twitter上的日期反序列化为。我的程序在<code>created_at</code>字段反序列化时失败。 我的域名类 我的解析方法 两个测试都失败,java.time.ZonedDateTime 类型的值。 我在Stackoverflow上检查了类似的问题,我的格式看起来是正确的。 我做错了? 解决 问题出在区域设置中。添加确切的区域设置后,测试开始通过。 对于<code>jackso

  • 我正在构建一个REST网络服务。某些类的属性类型为(JodaTime)。 将此对象发送给我的客户端(Javascript)时,我的对象 被转化为 问题是我把这个对象发回服务器时出错了,因为我无法实例化 我想有像-任何其他格式都可以。 环境 杰克逊-注释2.8.8 jackson-core 2.8.8 杰克逊-数据库2.8.8 jackson-datatype-joda 2.8.8 joda-tim