无法使用Final Field Bu Jackson反序列化最简单的对象 [英] Can't deserialize simplest Object with final field bu Jackson
问题描述
我只想序列化和反序列化简单的不可变对象,却不明白为什么我不能使用Jackson来完成
I just want to serialize and deserialize simple immutable object and don't understand why I can't do it using Jackson
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Value;
public class TestApplication {
@Value
static class Test {
private final String a;
}
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String res = objectMapper.writeValueAsString(new Test("test"));
System.out.println(res);
System.out.println(objectMapper.readValue(res, Test.class));
}
}
它失败,但出现以下异常:
It fails with exception:
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.devchallange.rogatakopita.RogatakopitaApplication$Test` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"a":"test"}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
at com.devchallange.rogatakopita.RogatakopitaApplication.main(RogatakopitaApplication.java:29)
我知道答案应该很简单,但是就像最普通的情况那样,不是可以直接使用的吗?
I understand that answer should be easy but it's like the most common case that should work from the box isn't it?
推荐答案
在设计不可变类时,Jackson应该使用所有必需的参数调用构造函数.
When designing immutable classes, Jackson should invoke the constructor with all the required arguments.
如果您不使用lombok,则
If you were not using lombok,
- 注释您希望Jackson用
@JsonCreator
调用的构造函数. - 用
@JsonProperty
注释构造函数参数.如果要跳过此操作,可以添加useParameterNamesModule
扩展名.
- Annotate the constructor you want Jackson to invoke with
@JsonCreator
. - Annotate the constructor parameters with
@JsonProperty
. If you want to skip this, you can add useParameterNamesModule
extension.
示例:
static class Test {
private final String a;
public Test() {
a = "default";
}
@JsonCreator // Jackson will use this constructor during deserialization
public Test(@JsonProperty("a") String a) { // @JsonProperty can be skipped if you use ParameterNamesModule annotation
this.a = a;
}
// Getter for A
}
Lombok的@Value
注释仅生成一个单一的all-args构造函数,我们需要使用@JsonCreator
进行注释.这可以通过用@AllArgsConstructor(onConstructor = @__(@JsonCreator))
注释类来完成.
Lombok's @Value
annotation produces only a single all-args constructor which we need to annotate with @JsonCreator
. This can be done by annotating the class with @AllArgsConstructor(onConstructor = @__(@JsonCreator))
.
由于构造函数是自动生成的,因此我们将无法使用@JsonProperty
注释参数,因此,您将不得不使用ParameterNamesModule
.
Since the constructor is auto-generated, we will not be able to annotate the parameters with @JsonProperty
, so, you'll have to use ParameterNamesModule
.
具有以下更改的代码段:
Code snippet with these changes:
public class TestApplication {
@Value
@AllArgsConstructor(onConstructor = @__(@JsonCreator))
static final class Test {
private final String a;
}
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new ParameterNamesModule());
String res = objectMapper.writeValueAsString(new Test("test"));
System.out.println(res);
System.out.println(objectMapper.readValue(res, Test.class));
}
}
以下是参数名称模块的maven依赖项.
Following is the maven dependency for parameter names module.
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>2.9.8</version>
<scope>compile</scope>
</dependency>
这篇关于无法使用Final Field Bu Jackson反序列化最简单的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!