【问题标题】:Deserialize Instant.ofEpochSecond() object format to Instant?将 Instant.ofEpochSecond() 对象格式反序列化为 Instant?
【发布时间】:2018-12-26 21:19:27
【问题描述】:

我定义了以下模型

public class ItemDetail {
    private final String name;
    private final String id;
    private final Instant someDate;
}

我将someDate 设置为setSomeDate(Instant.ofEpochSecond(resultSet.getLong("someDate"))。我正在从数据库中读取此内容。

我正在序列化此模型以返回以下响应,其中 someDate 被分配为 Instant.ofEpochSecond()

{
  "name": "Some nights",
  "id": "XYZZ01AS",
  "someDate": {
        "nano": 0,
        "epochSecond": 1292486400
    }
}

我的客户端代码解析了这个响应,我对输出很好。

现在,我想对此进行测试,并希望在我的测试中反序列化此响应。假设上述响应存储在response 变量中。

String response = ..... //string containing json response same as above format 
ItemDetail itemDetail = objectMapper.readValue(response, ItemDetail.class);

即使在注册new ObjectMapper().registerModule(new JavaTimeModule()) 之后这也不起作用(很明显)。 它抛出以下错误

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected one of [VALUE_STRING, VALUE_NUMBER_INT, VALUE_NUMBER_FLOAT] for java.time.Instant value 

在不实现自定义反序列化器的情况下,是否可以使这项工作正常进行?

注意:我只是想将其作为测试的一部分,并不打算对定义的模型 ItemDetail 进行任何更改。

【问题讨论】:

  • nano 是如何参与其中的?
  • 似乎JavaTimeModule 在序列化期间未激活。输出显示Instant 是使用默认对象序列化程序序列化的。应该是"someDate":1292486400.000000000
  • @alexander.egger 我基本上是从数据库结果集中读取一个长对象,然后将其转换为 Instant,如问题所示(已编辑)。谢谢
  • 问题在于嵌套结构。如果您无法更改模型,则可能必须执行以下操作:baeldung.com/jackson-nested-values

标签: java serialization jackson objectmapper


【解决方案1】:

JavaTimeModule 应该在序列化期间处于活动状态 new ObjectMapper().registerModule(new JavaTimeModule()); 。否则,Objectmapper 会将 Instant 数据类型转换为具有 epochSecondnano 的嵌套对象

【讨论】:

  • @Sachin - 请您在这里指导我:stackoverflow.com/questions/58014230/…
  • 公共静态 ObjectMapper getObjectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule());返回映射器; }
【解决方案2】:

你可以像这样使用 Jackson MixIn

public abstract class InstantMixIn {

    public InstantMixIn(
            @JsonProperty("epochSecond") long epochSecond,
            @JsonProperty("nano") int nanos) {
    }

}

以下代码显示了此 MixIn 与您的示例的用法

    ItemDetail itemDetail = new ItemDetail("XYZZ01AS", "Some nights", Instant.ofEpochSecond(1292486400L));

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.addMixIn(Instant.class, InstantMixIn.class);
    String response = objectMapper.writeValueAsString(itemDetail);
    System.out.println(response);
    itemDetail = objectMapper.readValue(response, ItemDetail.class);

【讨论】:

  • 谢谢。但我不能添加额外的课程。所以,我认为定制的序列化器是唯一的选择
  • 如果你可以使用自定义序列化器,你也应该可以使用 MixIn。 MixIn 并不意味着您必须在整个代码中使用 InstantMixIn 而不是 Instant。只需要在那一行告诉杰克逊如何处理 Instant。
猜你喜欢
  • 2016-07-15
  • 1970-01-01
  • 2021-12-02
  • 2011-08-14
  • 1970-01-01
  • 2021-12-16
  • 2020-05-10
相关资源
最近更新 更多