Perché quando un costruttore viene annotato con @JsonCreator, i suoi argomenti devono essere annotati con @JsonProperty?


109

In Jackson, quando annoti un costruttore con @JsonCreator, devi annotare i suoi argomenti con @JsonProperty. Quindi questo costruttore

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

diventa questo:

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

Non capisco perché sia ​​necessario. Puoi spiegare per favore?

Risposte:


113

Jackson deve sapere in quale ordine passare i campi da un oggetto JSON al costruttore. Non è possibile accedere ai nomi dei parametri in Java utilizzando la reflection: ecco perché è necessario ripetere queste informazioni nelle annotazioni.


9
Questo non è valido per Java8
MariuszS

12
@MariuszS Questo è vero, ma questo post spiega come sbarazzarsi di annotazioni estranee con l'aiuto del flag del compilatore Java8 e un modulo Jackson. Ho testato l'approccio e funziona.
quantum

Naturalmente, funziona a meraviglia
MariuszS

52

I nomi dei parametri normalmente non sono accessibili dal codice Java in fase di runtime (perché viene rilasciato dal compilatore), quindi se desideri quella funzionalità devi utilizzare la funzionalità integrata di Java 8 o utilizzare una libreria come ParaNamer per ottenere l'accesso ad esso.

Quindi, per non dover utilizzare annotazioni per gli argomenti del costruttore quando si usa Jackson, è possibile utilizzare uno di questi 2 moduli Jackson:

parametri nomi jackson-modulo-

Questo modulo consente di ottenere argomenti del costruttore senza annotazioni quando si utilizza Java 8 . Per utilizzarlo devi prima registrare il modulo:

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

Quindi compila il tuo codice usando il flag -parameters:

javac -parameters ...

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

Jackson-module-paranamer

Quest'altro richiede semplicemente di registrare il modulo o configurare un'annotazione introspezione (ma non entrambi, come sottolineato dai commenti). Consente di utilizzare argomenti del costruttore senza annotazioni sulle versioni di Java precedenti alla 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());

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




6

Si può semplicemente usare l'annotazione java.bean.ConstructorProperties: è molto meno prolissa e anche Jackson la accetta. Per esempio :

  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

Quando ho capito questo correttamente, sostituire il costruttore di default con uno parametrizzata e quindi devono descrivere le chiavi JSON che vengono utilizzati per chiamare il costruttore con.


3

Come specificato nella documentazione dell'annotazione , l'annotazione indica che il nome dell'argomento viene utilizzato come nome della proprietà senza alcuna modifica, ma può essere specificato su un valore non vuoto per specificare un nome diverso:


0

Basta incontrarlo e avere una risposta da qualche parte. puoi usare l'annotazione sotto dalla 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;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.