为什么在使用@JsonCreator注释构造函数时,必须使用@JsonProperty注释其参数?


108

在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;
}

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

Answers:


112

Jackson必须知道以什么顺序将字段从JSON对象传递给构造函数。使用反射无法在Java中访问参数名称-这就是为什么您必须在批注中重复此信息的原因。


9
这不适用于Java8
MariuszS 2015年

12
@MariuszS是的,但是这篇文章解释了如何在Java8编译器标志和Jackson模块的帮助下摆脱多余的注释。我已经测试了这种方法,并且有效。
量子


52

Java代码通常在运行时无法访问参数名称(因为它会被编译器删除),因此,如果要使用该功能,则需要使用Java 8的内置功能或使用诸如ParaNamer之类的库才能获得访问权限对它。

因此,为了在使用Jackson时不必在构造函数参数中使用批注,可以使用以下2个Jackson模块之一:

杰克逊模块参数名称

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

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

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

javac -parameters ...

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

杰克逊模块参数

这另一项仅需要您注册模块或配置注释自检(但不能同时如注释所指出的那样)。它允许您在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




6

可以简单地使用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;
  }

4

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



0

只是碰到它,并在某个地方得到答案。从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;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.