web-dev-qa-db-fra.com

Pourquoi, lorsqu'un constructeur est annoté avec @JsonCreator, ses arguments doivent être annotés avec @JsonProperty?

Dans Jackson, lorsque vous annotez un constructeur avec @JsonCreator, vous devez annoter ses arguments avec @JsonProperty. Donc ce constructeur

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

devient ceci:

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

Je ne comprends pas pourquoi c'est nécessaire. Pouvez-vous s'il vous plaît expliquer?

88
Ori Popowski

Jackson doit savoir dans quel ordre passer les champs d'un objet JSON au constructeur. Il n’est pas possible d’accéder aux noms de paramètre dans Java en utilisant la réflexion - c’est pourquoi vous devez répéter cette information dans les annotations.

95
Lukasz Wiktor

Les noms de paramètres ne sont normalement pas accessibles par le code Java au moment de l'exécution (car il est déposé par le compilateur)]. Par conséquent, si vous souhaitez utiliser cette fonctionnalité, vous devez soit utiliser Java = La fonctionnalité intégrée de 8 ou utilisez une bibliothèque telle que ParaNamer pour pouvoir y accéder.

Donc, pour ne pas avoir à utiliser des annotations pour les arguments du constructeur lors de l'utilisation de Jackson, vous pouvez utiliser l'un de ces 2 modules de Jackson:

noms de paramètres de module jackson

Ce module vous permet d'obtenir des arguments de constructeur sans annotation lors de l'utilisation de Java 8 . Pour l'utiliser, vous devez d'abord enregistrer le module:

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

Puis compilez votre code en utilisant le drapeau -parameters:

javac -parameters ...

Lien: https://github.com/FasterXML/jackson-modules-Java8/tree/master/parameter-names

jackson-module-paranamer

Cet autre exige simplement que vous enregistriez le module ou que vous configuriez une introspection d'annotation (mais pas les deux comme le soulignent les commentaires). Il vous permet d'utiliser des arguments de constructeur sans annotation sur les versions de Java antérieures à 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());

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

45
Rodrigo Quesada

Il est possible d'éviter les annotations du constructeur avec jdk8, où le compilateur introduira éventuellement des métadonnées avec les noms des paramètres du constructeur. Ensuite, avec nom-paramètre-module-jackson module, Jackson peut utiliser ce constructeur. Vous pouvez voir un exemple au message Jackson sans annotations

23
Manos Nikolaidis

Parce que Java ne conserve pas les noms des arguments de méthode ou de constructeur.

6
lcfd

Quand je comprends this correctement, vous remplacez le constructeur par défaut par un constructeur et vous devez donc décrire les clés JSON utilisées pour appeler le constructeur.

4
Smutje

Comme précisé dans la documentation d'annotation , l'annotation indique que le nom de l'argument est utilisé comme nom de propriété sans aucune modification, mais il peut être spécifié avec une valeur non vide pour spécifier un nom différent:

3
Guy Bouallet

On peut simplement utiliser l'annotation Java.bean.ConstructorProperties - c'est beaucoup moins verbeux et Jackson l'accepte également. Par exemple :

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