Quando viene utilizzata la proprietà @JsonProperty ea cosa serve?


183

Questo bean "State":

public class State {

    private boolean isSet;

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

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

}

viene inviato via cavo utilizzando il callback "successo" di ajax:

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

L'annotazione @JsonProperty è richiesta qui? Qual è il vantaggio di usarlo? Penso di poter rimuovere questa annotazione senza causare effetti collaterali.

Leggendo di questa annotion su https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations Non so quando è necessario utilizzarlo?


Risposte:


238

Ecco un buon esempio. Lo uso per rinominare la variabile perché JSON proviene da un .Netambiente in cui le proprietà iniziano con una lettera maiuscola.

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

Questo analizza correttamente da / verso JSON:

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

1
Le variabili del membro String non possono essere rinominate nel loro caso corretto, quindi nome stringa pubblico; diventa nome stringa pubblico; ?
cielo blu,

14
Sì, possono, ma in un ambiente Java che li rende non conformi agli standard di codifica. Riguarda più la mia pedanteria che un vero problema di codifica, ma è un buon ma semplice esempio di un uso reale @JsonPropertydell'annotazione.
OldCurmudgeon,

Questa annotazione può essere utilizzata per il membro di tipo Double? Mi chiedo solo se il tipo deve essere Stringo qualsiasi tipo supportato da JSON? Potrebbe essere di qualsiasi tipo? @OldCurmudgeon
Dreamer,

3
@Dreamer Sì. Il tipo è irrilevante. Questo influisce solo sul nome .
OldCurmudgeon,

1
@Pavan - Non avrà nulla a che fare con la denominazione. Mi piacerebbe Immagino che si dovrebbe esaminare il setter.
OldCurmudgeon,

44

Penso che OldCurmudgeon e StaxMan siano entrambi corretti, ma ecco una risposta a una frase con un semplice esempio per te.

@JsonProperty (nome), indica a Jackson ObjectMapper di mappare il nome della proprietà JSON sul nome del campo Java con annotazioni.

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

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

Il nome della classe dovrebbe essere uguale all'elemento radice di JSON? Questo non funziona per me.
Pavan,

39

bene per quello che vale ora ... JsonProperty è anche usato per specificare i metodi getter e setter per la variabile oltre alla solita serializzazione e deserializzazione. Ad esempio supponiamo di avere un payload come questo:

{
  "check": true
}

e una classe Deserializer:

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

Quindi in questo caso è necessaria l'annotazione JsonProperty. Tuttavia, se hai anche un metodo nella classe

public class Check {

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

  public Boolean getCheck() {
     return check;
  }
}

Dai un'occhiata anche a questa documentazione: http://fasterxml.github.io/jackson-annotations/javadoc/2.3.0/com/fasterxml/jackson/annotation/JsonProperty.html


15

Senza annotazioni, il nome della proprietà dedotto (corrispondente a JSON) sarebbe "impostato" e non - come sembra essere l'intento - "isSet". Questo perché secondo la specifica Java Beans, i metodi del modulo "isXxx" e "setXxx" sono considerati come significanti che esiste una proprietà logica "xxx" da gestire.


1
Questa è la risposta corretta per il caso specifico indicato nella domanda
Andrew Spencer,

6

Come sapete, si tratta di serializzare e desalinizzare un oggetto. Supponiamo che ci sia un oggetto:

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

La serializzazione di questo oggetto è:

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

Il nome della variabile viene utilizzato direttamente per serializzare i dati. Se si sta per rimuovere l'API di sistema dall'implementazione del sistema, in alcuni casi, è necessario rinominare la variabile in serializzazione / deserializzazione. @JsonProperty è un metadati per dire al serializzatore come eseguire l'oggetto seriale. È usato per:

  • nome della variabile
  • accesso (LEGGI, SCRIVI)
  • valore predefinito
  • richiesta / optional

dall'esempio:

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

6

L'aggiunta di JsonProperty garantisce anche la sicurezza nel caso in cui qualcuno decida di voler cambiare uno dei nomi delle proprietà senza rendersi conto che la classe in questione verrà serializzata su un oggetto Json. Se cambiano il nome della proprietà, JsonProperty garantisce che verrà utilizzato nell'oggetto Json e non nel nome della proprietà.


3

Oltre alle altre risposte, l' @JsonPropertyannotazione è molto importante se si utilizza l' @JsonCreatorannotazione in classi che non hanno un costruttore 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);
    }
}

In questo esempio, l'unico costruttore è contrassegnato come @JsonCreator, pertanto Jackson utilizzerà questo costruttore per creare l'istanza. Ma l'output è come:

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

Eccezione nel thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: impossibile costruire l'istanza di ClassToSerialize $ MyEnum dal valore String 'stringValue': valore non uno dei nomi di istanza Enum dichiarati: [FIRST, SECOND, THIRD]

Ma dopo l'aggiunta @JsonPropertydell'annotazione nel costruttore:

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

La deserializzazione ha esito positivo:

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

StringValue: ABCD

MyEnum: PRIMO


2

Oltre a tutte le risposte sopra, non dimenticare la parte della documentazione che dice

Annotazione marcatore che può essere utilizzata per definire un metodo non statico come "setter" o "getter" per una proprietà logica (a seconda della sua firma) o campo oggetto non statico da utilizzare (serializzato, deserializzato) come logico proprietà.

Se hai un non-staticmetodo nella tua classe che non è un convenzionale getter or setter, puoi farlo agire come un getter and setterusando l'annotazione su di esso. Vedi l'esempio sotto

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

Quando l'oggetto sopra è serializzato, la risposta conterrà

  • nome utente da getUsername()
  • id da getId()
  • idAndUsername da getIdAndUsername*

Dal momento che il metodo getIdAndUsernameinizia getquindi viene trattato come un normale getter, quindi perché potresti annotarlo @JsonIgnore.

Se hai notato che concatenateIdAndUsernamenon viene restituito e questo perché il nome non inizia con gete se desideri che il risultato di quel metodo sia incluso nella risposta, puoi utilizzare @JsonProperty("...")e verrebbe trattato normalmente getter/settercome indicato nella documentazione evidenziata sopra .


0

Da JsonProperty javadoc,

Definisce il nome della proprietà logica, ovvero il nome del campo oggetto JSON da utilizzare per la proprietà. Se il valore è vuoto String (che è l'impostazione predefinita), proverà a utilizzare il nome del campo annotato.

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.