为什么构造函数使用@JsonCreator进行注释时,其参数必须使用@Json Property进行注释



在Jackson中,用@JsonCreator注释构造函数时,必须用@JsonProperty注释其参数。所以这个构造函数

public Point(double x, double y) {
this.x = x;
this.y = y;
}

变为:

@JsonCreator
public Point(@JsonProperty("x") double x, @JsonProperty("y") double y) {
this.x = x;
this.y = y;
}

我不明白为什么有必要。你能解释一下吗?

Jackson必须知道从JSON对象向构造函数传递字段的顺序。在Java中,使用反射访问参数名称是不可能的——这就是为什么必须在注释中重复这些信息。

Java代码在运行时通常无法访问参数名称(因为它是由编译器丢弃的),因此如果您想要该功能,您需要使用Java 8的内置功能或使用ParaNamer等库才能访问它。

因此,为了在使用Jackson时不必为构造函数参数使用注释,您可以使用以下两个Jackson模块中的任何一个:

jackson模块参数名称

此模块允许您在使用Java8时获得无注释的构造函数参数。为了使用它,您首先需要注册模块:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ParameterNamesModule());

然后使用-parameters标志编译代码:

javac -parameters ...

链接:https://github.com/FasterXML/jackson-modules-java8/tree/master/parameter-names

杰克逊模paranamer

另一个只是要求您注册模块或配置注释内省(但不是如注释所指出的那样两者都需要)。它允许您在1.8之前的版本的Java上使用无注释构造函数参数。

ObjectMapper mapper = new ObjectMapper();
// either via module
mapper.registerModule(new ParanamerModule());
// or by directly assigning annotation introspector (but not both!)
mapper.setAnnotationIntrospector(new ParanamerOnJacksonAnnotationIntrospector());

链接:https://github.com/FasterXML/jackson-modules-base/tree/master/paranamer

使用jdk8可以避免构造函数注释,编译器可以选择引入带有构造函数参数名称的元数据。然后使用jackson模块参数名称,模块jackson可以使用这个构造函数。你可以在后杰克逊看到一个没有注释的例子

  • Java™教程-获取方法参数的名称

可以简单地使用java.bean.ConstructorProperties注释-它不那么冗长,Jackson也接受它。例如:

import java.beans.ConstructorProperties;
@ConstructorProperties({"answer","closed","language","interface","operation"})
public DialogueOutput(String answer, boolean closed, String language, String anInterface, String operation) {
this.answer = answer;
this.closed = closed;
this.language = language;
this.anInterface = anInterface;
this.operation = operation;
}

因为Java字节码不保留方法或构造函数参数的名称。

当我正确理解这一点时,您可以将默认构造函数替换为参数化构造函数,因此必须描述用于调用构造函数的JSON键。

正如注释文档中所指出的,注释指示参数名称用作属性名称而不进行任何修改,但可以将其指定为非空值以指定不同的名称:

只要遇到它,就会在某个地方得到答案。您可以从2.7.0 开始使用以下注释

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class Point {
final private double x;
final private double y;
@ConstructorProperties({"x", "y"})
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}

最新更新