问题描述
我将代码从Java 8和Sprint Boot 1.X迁移到11和2.X时遇到一个奇怪的问题。以前,我发现Jackson将private boolean isAvailable
和available: 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输出中为您提供这两种变体。