Почему, когда конструктор аннотируется с помощью @JsonCreator, его аргументы должны быть аннотированы с помощью @JsonProperty?

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

Я не понимаю, зачем это нужно. Не могли бы вы объяснить?

Ответ 1

Джексон должен знать, в каком порядке передать поля из объекта JSON в конструктор. Невозможно получить доступ к именам параметров в Java с помощью отражения - почему вы должны повторять эту информацию в аннотации.

Ответ 2

Имена параметров, как правило, недоступны кодом Java во время выполнения (потому что они упускаются компилятором), поэтому, если вам нужна эта функциональность, вам нужно либо использовать встроенные функции Java 8, либо использовать библиотеку, такую как ParaNamer, чтобы получить доступ к нему.

Поэтому, чтобы не использовать аннотации для аргументов конструктора при использовании Jackson, вы можете использовать любой из этих двух модулей 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

ДЖЕКСОН-модуль-paranamer

Этот другой просто требует, чтобы вы зарегистрировали модуль или сконфигурировали интроспекцию аннотации (но не оба, как указано в комментариях). Он позволяет использовать аргументы конструктора без аннотации в версиях Java до 1.8.

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

Ответ 3

Можно избежать аннотаций конструктора с помощью jdk8, где, возможно, компилятор будет вводить метаданные с именами параметров конструктора. Затем с помощью jackson-module-parameter-names модуль Jackson может использовать этот конструктор. Вы можете увидеть пример в post Джексон без аннотаций

Ответ 4

Поскольку байт-код Java не сохраняет имена аргументов метода или конструктора.

Ответ 5

Когда я правильно понимаю this, вы заменяете конструктор по умолчанию параметризованным и, следовательно, должны описывать ключи JSON, которые используются для вызова конструктор с.

Ответ 6

Как указано в аннотации документации, аннотация указывает, что имя аргумента используется как имя свойства без каких-либо изменений, но оно может указывается непустое значение, чтобы указать другое имя:

Ответ 7

Можно просто использовать аннотацию java.bean.ConstructorProperties - она намного менее многословна, и Джексон также принимает ее. Например:

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