Dlaczego, gdy konstruktor jest oznaczony adnotacją @JsonCreator, jego argumenty muszą być opatrzone adnotacją @JsonProperty?


109

W Jackson, kiedy dodajesz adnotację do konstruktora za pomocą @JsonCreator, musisz dodać adnotację do jego argumentów za pomocą @JsonProperty. Więc ten konstruktor

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

staje się tym:

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

Nie rozumiem, dlaczego jest to konieczne. Czy możesz wyjaśnić?

Odpowiedzi:


113

Jackson musi wiedzieć, w jakiej kolejności przekazuje pola z obiektu JSON do konstruktora. Nie ma możliwości dostępu do nazw parametrów w Javie za pomocą refleksji - dlatego trzeba powtarzać te informacje w adnotacjach.


9
Nie dotyczy to Java8
MariuszS

12
@MariuszS To prawda, ale ten post wyjaśnia, jak pozbyć się zbędnych adnotacji za pomocą flagi kompilatora Java8 i modułu Jacksona. Przetestowałem to podejście i działa.
Quantum


52

Nazwy parametrów zwykle nie są dostępne dla kodu Java w czasie wykonywania (ponieważ są upuszczane przez kompilator), więc jeśli chcesz mieć tę funkcję, musisz albo użyć wbudowanej funkcjonalności Java 8, albo użyć biblioteki, takiej jak ParaNamer, aby uzyskać dostęp do tego.

Aby więc nie używać adnotacji jako argumentów konstruktora podczas korzystania z Jacksona, możesz użyć jednego z tych 2 modułów Jacksona:

nazwy-parametrów-modułów-jackson

Ten moduł umożliwia uzyskanie argumentów konstruktora bez adnotacji podczas korzystania z języka Java 8 . Aby z niego skorzystać należy najpierw zarejestrować moduł:

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

Następnie skompiluj swój kod za pomocą flagi -parameters:

javac -parameters ...

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

paranamer-module-jackson

Ten drugi wymaga po prostu zarejestrowania modułu lub skonfigurowania introspekcji adnotacji (ale nie obu, jak wskazują komentarze). Pozwala na użycie argumentów konstruktora bez adnotacji w wersjach Java wcześniejszych niż 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());

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




6

Można po prostu użyć adnotacji java.bean.ConstructorProperties - jest znacznie mniej szczegółowa i Jackson również ją akceptuje. Na przykład :

  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

Kiedy dobrze to rozumiem , zastępujesz domyślny konstruktor sparametryzowanym i dlatego musisz opisać klucze JSON, które są używane do wywoływania konstruktora.


3

Jak wyjaśniono w dokumentacji adnotacji , adnotacja wskazuje, że nazwa argumentu jest używana jako nazwa właściwości bez żadnych modyfikacji, ale można określić niepustą wartość, aby określić inną nazwę:


0

Po prostu znajdź to i gdzieś otrzymałem odpowiedź. możesz użyć poniższej adnotacji od 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;
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.