【问题标题】:Avoid constructor calls when deserializing with jackson使用jackson反序列化时避免构造函数调用
【发布时间】:2020-10-20 17:26:47
【问题描述】:

我有一个类,它有一个在构造函数中生成的UUID 属性,所以这意味着它是在每次创建新对象时生成的。

我正在使用 Jackson 将 json 字符串反序列化为带有 ObjectMapper 的对象。问题是当我反序列化时,它将json字符串反序列化为一个新对象,并调用该类的构造函数,从而生成一个新的UUID。所以基本上它需要一个已经有UUID的Json字符串,当它反序列化时它会改变它为一个新的。

任何想法如何使用 Jackson 解决这个问题?

【问题讨论】:

  • 我很惊讶 UUID 没有被 JSON 中的 UUID 覆盖。 UUID 是最终的吗?
  • 当我使用 Gson 时,我发现没有发生同样的问题,这就是为什么我相信 Jackson 也可以通过某种方式避免它。
  • @JoseMartinez 这不是最终的,我也很惊讶。
  • 它被转换成这样的字符串 -> uuid = UUID.randomUUID().toString();
  • 对不起,我无权分享代码。该bean只是具有问题中提到的构造函数的常规bean。不过,有一件事似乎很可疑。 UUID 属性的设置器检查属性是否为空,如果不为空则不设置它。这可能是问题吗?也许是因为这个 setter 而没有重写?

标签: java json constructor jackson deserialization


【解决方案1】:

您可以添加第二个私有构造函数并使用@JsonCreator 注释此构造函数。这将使 Jackson 使用此构造函数进行反序列化。您可以向构造函数添加其他参数并使用 @JsonProperty 注释参数 - 我认为 - 以使 Jackson 正确设置相应的值。

【讨论】:

  • 很好,只是一个问题,当我自己创建新对象时,是否使用了带有此注释的构造函数?
  • 如果将构造函数设为私有,则不能从外部使用。
  • 对不起,我错过了那部分。
【解决方案2】:

我无法重现该问题。下面是我的代码。它按预期工作。

public static class MyPojo {
    private String id;

    public MyPojo() {
        this.id = UUID.randomUUID().toString();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}


public static void main(String[] args) throws JsonProcessingException {
    var om = new ObjectMapper();
    var myPojo = om.readValue(" {\"id\":\"6d1eab11-d64f-4152-9955-3d5c54828cd9\"}", MyPojo.class);
    assertThat(myPojo.id).isEqualTo("6d1eab11-d64f-4152-9955-3d5c54828cd9");
    System.out.println("id = " + myPojo.id);
}

【讨论】:

  • setter 正在检查 id 是否为 null,如果不是,则没有设置它。这就是问题所在。感谢您的帮助,我赞成您的回答,因为它有很大帮助。
【解决方案3】:

问题是我有一个设置器来检查UUID 是否为空,如果不是,它没有将它设置为新的。因此,当创建对象时,它会自动获得UUID,而杰克逊无法使用 setter 设置它,因为它不为空。当我从设置器中删除 if 时,它工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    相关资源
    最近更新 更多