web-dev-qa-db-fra.com

Quand la propriété @JsonProperty est-elle utilisée et à quoi sert-elle?

Ce haricot 'State':

public class State {

    private boolean isSet;

    @JsonProperty("isSet")
    public boolean isSet() {
        return isSet;
    }

    @JsonProperty("isSet")
    public void setSet(boolean isSet) {
        this.isSet = isSet;
    }

}

est envoyé sur le fil à l'aide du rappel ajax 'success':

        success : function(response) {  
            if(response.State.isSet){   
                alert('success called successfully)
            }

L'annotation @JsonProperty est-elle requise ici? Quel est l'avantage de l'utiliser? Je pense que je peux supprimer cette annotation sans provoquer d'effets secondaires.

Lire à propos de cette annonce sur https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations Je ne sais pas quand cela doit être utilisé?

144
blue-sky

Voici un bon exemple. Je l'utilise pour renommer la variable car le JSON provient d'un environnement .Net où les propriétés commencent par une lettre majuscule.

public class Parameter {
  @JsonProperty("Name")
  public String name;
  @JsonProperty("Value")
  public String value; 
}

Ceci analyse correctement vers/depuis le JSON:

"Parameter":{
  "Name":"Parameter-Name",
  "Value":"Parameter-Value"
}
191
OldCurmudgeon

Je pense que OldCurmudgeon et StaxMan sont tous les deux corrects, mais voici une réponse en une phrase avec un exemple simple pour vous.

@JsonProperty (name), indique à Jackson ObjectMapper de mapper le nom de la propriété JSON au nom du champ annoté Java.

//example of json that is submitted 
"Car":{
  "Type":"Ferrari",
}

//where it gets mapped 
public static class Car {
  @JsonProperty("Type")
  public String type;
 }
34
grepit

jsonProperty est également utilisé pour spécifier les méthodes de lecture et de définition de la variable en dehors de la sérialisation et de la désérialisation habituelles. Par exemple, supposons que vous ayez une charge comme celle-ci:

{
  "check": true
}

et une classe de désérialiseur:

public class Check {

  @JsonProperty("check")    // It is needed else Jackson will look got getCheck method and will fail
  private Boolean check;

  public Boolean isCheck() {
     return check;
  }
}

Ensuite, dans ce cas, l'annotation JsonProperty est nécessaire. Cependant si vous avez aussi une méthode dans la classe

public class Check {

  //@JsonProperty("check")    Not needed anymore
  private Boolean check;

  public Boolean getCheck() {
     return check;
  }
}

Consultez également cette documentation: http://fasterxml.github.io/jackson-annotations/javadoc/2.3.0/com/fasterxml/jackson/annotation/JsonProperty.html

31
Richeek

Sans les annotations, le nom de propriété inféré (à faire correspondre à partir de JSON) serait "défini" et non - comme cela semble être l'intention - "isSet". En effet, conformément à la spécification Java Beans, les méthodes de formulaire "isXxx" et "setXxx" signifient qu'il existe une propriété logique "xxx" à gérer.

12
StaxMan

Comme vous le savez, il s’agit de sérialiser et de dessaler un objet. Supposons qu'il y ait un objet:

public class Parameter {
  public String _name;
  public String _value; 
}

La sérialisation de cet objet est:

{
  "_name": "...",
  "_value": "..."
}

Le nom de la variable est directement utilisé pour sérialiser les données. Si vous êtes sur le point de supprimer une API du système de son implémentation, vous devez dans certains cas renommer la variable lors de la sérialisation/désérialisation. @JsonProperty est une métadonnée pour indiquer au sérialiseur comment mettre en série un objet. Il est utilisé pour:

  • nom de variable
  • accès (LIRE, ÉCRIRE)
  • valeur par défaut
  • obligatoire/facultatif

par exemple:

public class Parameter {
  @JsonProperty(
        value="Name",
        required=true,
        defaultValue="No name",
        access= Access.READ_WRITE)
  public String _name;
  @JsonProperty(
        value="Value",
        required=true,
        defaultValue="Empty",
        access= Access.READ_WRITE)
  public String _value; 
}
3
Mostafa

L'ajout de JsonProperty garantit également la sécurité au cas où quelqu'un déciderait de modifier l'un des noms de propriété ne réalisant pas que la classe en question serait sérialisé en objet Json. Si elles changent le nom de la propriété, JsonProperty s'assure qu'il sera utilisé dans l'objet Json, et non le nom de la propriété.

3
arush436

En plus d'autres réponses, l'annotation @JsonProperty est vraiment importante si vous utilisez l'annotation @JsonCreator dans les classes qui n'ont pas de constructeur no-arg.

public class ClassToSerialize {

    public enum MyEnum {
        FIRST,SECOND,THIRD
    }

    public String stringValue = "ABCD";
    public MyEnum myEnum;


    @JsonCreator
    public ClassToSerialize(MyEnum myEnum) {
        this.myEnum = myEnum;
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        ClassToSerialize classToSerialize = new ClassToSerialize(MyEnum.FIRST);
        String jsonString = mapper.writeValueAsString(classToSerialize);
        System.out.println(jsonString);
        ClassToSerialize deserialized = mapper.readValue(jsonString, ClassToSerialize.class);
        System.out.println("StringValue: " + deserialized.stringValue);
        System.out.println("MyEnum: " + deserialized.myEnum);
    }
}

Dans cet exemple, le seul constructeur est marqué comme @JsonCreator, Jackson utilisera donc ce constructeur pour créer l'instance. Mais le résultat est comme:

Serialized: {"stringValue": "ABCD", "myEnum": "FIRST"}

Exception dans le thread "principal" com.fasterxml.jackson.databind.exc.InvalidFormatException: impossible de construire une instance de ClassToSerialize $ MyEnum à partir de String value 'stringValue': valeur différente des noms d'instance Enum déclarés: [FIRST, SECOND , TROISIEME]

Mais après l’ajout de l’annotation @JsonProperty dans le constructeur:

@JsonCreator
public ClassToSerialize(@JsonProperty("myEnum") MyEnum myEnum) {
    this.myEnum = myEnum;
}

La désérialisation est réussie:

Sérialisé: {"myEnum": "FIRST", "stringValue": "ABCD"}

StringValue: ABCD

MyEnum: PREMIER

3
DVarga

En plus de toutes les réponses ci-dessus, n'oubliez pas la partie de la documentation qui dit

Annotation de marqueur pouvant être utilisée pour définir une méthode non statique en tant que "setter" ou "getter" pour une propriété logique (selon sa signature), ou un champ d'objet non statique à utiliser (en série, désérialisé) en tant que logique propriété.

Si vous avez une méthode non-static dans votre classe qui n'est pas une méthode conventionnelle getter or setter, vous pouvez la faire agir comme un getter and setter en utilisant l'annotation correspondante. Voir l'exemple ci-dessous

public class Testing {
    private Integer id;
    private String username;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getIdAndUsername() {
        return id + "." + username; 
    }

    public String concatenateIdAndUsername() {
        return id + "." + username; 
    }
}

Lorsque l'objet ci-dessus est sérialisé, la réponse contiendra

  • nom d'utilisateur de getUsername()
  • id de getId()
  • idAndUsername from getIdAndUsername *

Puisque la méthode getIdAndUsername commence par get, elle est traitée comme un getter normal. Par conséquent, vous pouvez l'annoter avec @JsonIgnore.

Si vous avez remarqué que concatenateIdAndUsername n'est pas renvoyé, c'est parce que son nom ne commence pas par get et si vous souhaitez que le résultat de cette méthode soit inclus dans la réponse, vous pouvez utiliser @JsonProperty("..."). être traité comme un getter/setter normal, comme indiqué dans la documentation mise en évidence ci-dessus.

0
Raf

De JsonProperty javadoc,

Définit le nom de la propriété logique, c'est-à-dire le nom de champ d'objet JSON à utiliser pour la propriété. Si valeur est vide String (valeur par défaut), essaiera d'utiliser le nom du champ annoté.

0
sc30