Java Can';t使用final字段反序列化最简单的对象
我只想序列化和反序列化简单的不可变对象,不明白为什么我不能用Jackson来实现Java Can';t使用final字段反序列化最简单的对象,java,jackson,Java,Jackson,我只想序列化和反序列化简单的不可变对象,不明白为什么我不能用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; }
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));
}
}
除以下情况外,它失败:
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)
我知道答案应该很简单,但这就像最常见的情况一样,应该从盒子里开始工作,不是吗?在java中,最终属性必须在构造函数中设置,并且只能稍后读取。
但杰克逊后来试图改变这个属性。因此,不能使用jackson来填充最后一个字段。在设计不可变类时,jackson应使用所有必需的参数调用构造函数 如果你没有使用龙目山
- 注释希望Jackson使用
调用的构造函数@JsonCreator
- 用
注释构造函数参数。如果要跳过此操作,可以添加use@JsonProperty
扩展名ParameterNamesModule
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
对其进行注释。这可以通过使用@allargsconstuctor(onConstructor=@\uuuu(@JsonCreator))
注释类来完成
由于构造函数是自动生成的,我们将无法使用@JsonProperty
注释参数,因此,您必须使用ParameterNamesModule
包含以下更改的代码段:
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依赖项
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>2.9.8</version>
<scope>compile</scope>
</dependency>
com.fasterxml.jackson.module
jackson模块参数名
2.9.8
编写
。因此,所提供的代码不可能产生所提供的异常。