背景:我在spring-admin项目中发现了“功能失调”的代码:“无法构造注册实例(不存在像默认构造一样的创建者)”。因此,我编写了自定义解串器并报告了该问题。但是报告被拒绝了,因为它据称可行。经过重新测试后,它现在似乎可以正常工作了。没有道理。所以我想知道为什么该代码有效。
但这是要抓住的地方。当我编写类似的测试类时,它在我的项目中不起作用。即使我从字面上接受“现在可以使用”的注册类的代码,并在自己的项目中尝试它,也不会反序列化。然后,使用几乎相同的类,它可以工作。没有任何意义。
以下文章介绍了龙目岛-杰克逊组合的工作原理,但此处不起作用。我完全感到困惑,这是令人难以置信的荒谬情况,其中(不必要的)简化会带来极高的复杂性。但我想了解一下,因为以后我可以再次遇到这种情况。
Jackson Deserialization Fails because of non-default constructor created by lombok
因此,要易于使用:这里我们有不错的工作纯杰克逊:
public class TestTO_pureJackson {
private final String a;
private final String b;
@JsonCreator
private TestTO_pureJackson(@JsonProperty("a") String a, @JsonProperty("b") String b) {
this.a = a;
this.b = b;
}
}
在这里,我们还没有使用等效的lombok(即使我删除了一个字段,因此与后一个示例“相同”):
@lombok.Data
public class TestTO {
private final String a;
private final String b;
@lombok.Builder(builderClassName = "Builder")
private TestTO(String a, String b) {
this.a = a;
this.b = b;
}
public static TestTO.Builder create(String a) {
return builder().a(a);
}
}
我们正在尝试反序列化:
{"a": "a", "b": "b"}
谁能理解引擎盖下的魔力,并帮助我了解这里出了什么问题?
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
并使它变得更加荒谬(您实际上看到了与TestTO的任何显着区别吗?),下面的代码起作用了:
@lombok.Data
public class Pair {
private final String left;
private final String right;
@lombok.Builder(builderClassName = "Builder")
private Pair(String pairId) {
left = pairId.substring(0, 3).toUpperCase(Locale.US);
right = pairId.substring(3).toUpperCase(Locale.US);
}
}
和主要方法:
public class PairTest {
public static final String DATA = "[\"btcusd\",\"ltcusd\",\"ltcbtc\"]";
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Pair[] pairs = objectMapper.readValue(DATA, Pair[].class);
for (Pair pair : pairs) {
System.out.println(pair);
}
}
}
有人能看到为什么两个几乎相同的TO类的行为不同吗?
答案 0 :(得分:2)
TestTO
不起作用,因为没有Jackson可以使用的构造函数。它不能使用two-args构造函数,因为它不知道应为哪个参数使用哪个JSON字段(因为在编译过程中会删除参数名称)。
对于Lombok生成的构造函数,您可以通过建议Lombok生成@ConstructorProperties
批注来解决。只需添加
lombok.anyConstructor.addConstructorProperties=true
您的lombok.config
。对于手动构造函数,您还可以简单地添加@JsonProperty
。
(请注意,Jackson不会自动使用构建器;您必须使用@JsonDeserialize
和@JsonPOJOBuilder
明确地告诉Jackson。)
TestTO_pureJackson
之所以有效,是因为@JsonProperty
在运行时可用,并且由Jackson用来确定映射。
Pair
之所以有效,是因为有一个可用的构造函数:Jackson不必猜测哪个参数属于哪个字段,因为只有一个。请注意,这仅适用于String
,int
,long
或boolean
单参构造函数。
Lombok不会不生成任何其他构造函数(此处为two-args构造函数)(如果已有的话)(请参见documentation of @Data
),因此这是类中唯一的构造函数。