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


в Джексоне, когда вы аннотируете конструктор с @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;
}

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

6 65

6 ответов:

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

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

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

jackson-module-parameter-names

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

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

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

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

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