Jackson序列化为一个Java变量输出两个json行

问题描述

我将代码从Java 8和Sprint Boot 1.X迁移到11和2.X时遇到一个奇怪的问题。以前,我发现Jackson将private boolean isAvailableavailable: false都序列化了。更令人困惑的是,龙目岛(Lombok)一直在兜风,所以我对吸气剂没有视线,如果这引起了冲突。下面是java类代码

isAvailable: false

Jackson Object映射器提供的JSON是:

@Data
public class Availability{

    @JsonProperty("isAvailable")
    private boolean isAvailable;

}

这是杰克逊2.8版本。现在,在Jackson 2.10中,我仅从ObjectMapper获得"Availability" : [{ "isAvailable" : false,"available" : false }] 作为JSON中的输出

isAvailable: false

在我看来,它应该仅与Java变量名称匹配,但是合同令人遗憾地同时具有两个版本,并且我不想更改合同。有些正在使用is,有些则没有。我知道可以使用自定义序列化程序,但不确定如何执行或是否有必要。

解决方法

这是龙目岛+领域,在互动。

让我们接受这个假设类(没有龙目岛,或者杰克逊在这里完全没有涉及

class Example {
    public boolean isAvailable() {
        return true;
    }
}

根据beanspec,Example类具有一个布尔类型为available的单个只读Bean属性。这是因为任何返回布尔值并以is(然后是大写字母)开头的无参数方法都算作访问器,并获取其名称,将is剥离掉

所以这就是从那端开始。现在,让我们从另一端来看它,编写一个类,无论出于何种原因,您都决定将该字段命名为isAvailable。真正的问题是:您希望“属性”以什么命名(根据beanspec)?如果确实要称其为isAvailable,则只有一种方法可以实现:

class Example {
    public boolean isIsAvailable() {
        return true;
    }
}

是的,isIsAvailable。看起来很愚蠢,但是如果您希望将属性本身称为isAvailable,这就是规则所决定的。 Lombok决定(来源:我是核心贡献者),当您在名为isIsAvailable的字段上粘贴@Getter注释时,没有人真的想要一个名为isAvailable的方法。

因此,就杰克逊而言,您现在拥有的类实际上是这样的:

class Availability {
    @JsonProperty("isAvailable") private boolean isAvailable;

    public boolean isAvailable() { return this.isAvailable; }
}

仅使用文字规则就不使用任何特殊的情报,这意味着杰克逊说:好的,这里有 2 个不同的属性,available(通过调用isAvailable()获得) ,和isAvailable字段。对于beanspec风格的吸气剂,is / get被剥夺了,对于字段则没有,特别是如果您在上面粘贴了@JsonProperty("isAvailable")

这就是为什么这一切发生的原因。

解决方案可能是采用这种方法:

@JsonProperty("available")
public boolean getAvailable() { return this.available; }

我认为这会在JSON输出中为您提供这两种变体。