Wann wird die Eigenschaft @JsonProperty verwendet und wofür wird sie verwendet?

181

Diese Bohne 'State':

public class State {

    private boolean isSet;

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

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

}

wird über die Leitung mit dem Ajax-Rückruf "Erfolg" gesendet:

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

Ist hier die Anmerkung @JsonProperty erforderlich? Was ist der Vorteil der Verwendung? Ich denke, ich kann diese Anmerkung entfernen, ohne Nebenwirkungen zu verursachen.

Lesen Sie über diese Anmerkung unter https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations. Ich weiß nicht, wann diese verwendet werden muss.

blauer Himmel
quelle

Antworten:

235

Hier ist ein gutes Beispiel. Ich verwende es, um die Variable umzubenennen, da der JSON aus einer .NetUmgebung stammt, in der Eigenschaften mit einem Großbuchstaben beginnen.

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

Dies analysiert korrekt den / vom JSON:

"Parameter":{
  "Name":"Parameter-Name",
  "Value":"Parameter-Value"
}
OldCurmudgeon
quelle
1
Können die String-Mitgliedsvariablen nicht in die richtige Groß- und Kleinschreibung umbenannt werden, also öffentlicher String-Name? wird öffentlich String Name; ?
blauer Himmel
14
Ja, das können sie, aber in einer Java-Umgebung, in der sie nicht den Codierungsstandards entsprechen. Es geht mehr um meine Pedanterie als um ein echtes Codierungsproblem, aber es ist ein gutes, aber einfaches Beispiel für eine echte Verwendung der @JsonPropertyAnnotation.
OldCurmudgeon
Kann diese Anmerkung für das Mitglied des Typs verwendet werden Double? Ich frage mich nur, ob der Typ sein muss Stringoder ein Typ, den JSON unterstützt. Könnte es irgendein Typ sein? @OldCurmudgeon
Dreamer
3
@ Träumer Ja. Der Typ ist irrelevant. Dies betrifft nur den Namen .
OldCurmudgeon
1
@Pavan - Das hat nichts mit der Benennung zu tun. Ich denke, Sie sollten Ihre Setter untersuchen.
OldCurmudgeon
44

Ich denke, OldCurmudgeon und StaxMan sind beide richtig, aber hier ist eine Satzantwort mit einem einfachen Beispiel für Sie.

@JsonProperty (Name) weist Jackson ObjectMapper an, den Namen der JSON-Eigenschaft dem Namen des mit Anmerkungen versehenen Java-Felds zuzuordnen.

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

//where it gets mapped 
public static class Car {
  @JsonProperty("Type")
  public String type;
 }
grepit
quelle
Sollte der Klassenname mit dem Stammelement von JSON identisch sein? Das funktioniert bei mir nicht.
Pavan
39

Gut für das, was es jetzt wert ist ... JsonProperty wird AUCH verwendet, um Getter- und Setter-Methoden für die Variable neben der üblichen Serialisierung und Deserialisierung anzugeben. Angenommen, Sie haben eine Nutzlast wie diese:

{
  "check": true
}

und eine Deserializer-Klasse:

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

In diesem Fall ist eine JsonProperty-Annotation erforderlich. Wenn Sie jedoch auch eine Methode in der Klasse haben

public class Check {

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

  public Boolean getCheck() {
     return check;
  }
}

Schauen Sie sich auch diese Dokumentation an: http://fasterxml.github.io/jackson-annotations/javadoc/2.3.0/com/fasterxml/jackson/annotation/JsonProperty.html

Richeek
quelle
15

Ohne Anmerkungen würde der abgeleitete Eigenschaftsname (der mit JSON übereinstimmt) "gesetzt" und nicht - wie es beabsichtigt zu sein scheint - "isSet". Dies liegt daran, dass gemäß der Java Beans-Spezifikation die Methoden der Form "isXxx" und "setXxx" bedeuten, dass die logische Eigenschaft "xxx" verwaltet werden muss.

StaxMan
quelle
1
Dies ist die richtige Antwort für den speziellen Fall in der Frage
Andrew Spencer
6

Wie Sie wissen, geht es hier darum, ein Objekt zu serialisieren und zu entsalzen. Angenommen, es gibt ein Objekt:

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

Die Serialisierung dieses Objekts lautet:

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

Der Name der Variablen wird direkt zum Serialisieren von Daten verwendet. Wenn Sie die System-API aus der Systemimplementierung entfernen möchten, müssen Sie in einigen Fällen die Variable bei der Serialisierung / Deserialisierung umbenennen. @JsonProperty sind Metadaten, die dem Serializer mitteilen, wie ein serielles Objekt erstellt werden soll. Es wird verwendet, um:

  • Variablennamen
  • Zugriff (LESEN, SCHREIBEN)
  • Standardwert
  • erforderlich / optional

aus Beispiel:

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; 
}
Mostafa
quelle
6

Das Hinzufügen der JsonProperty gewährleistet auch die Sicherheit für den Fall, dass jemand entscheidet, einen der Eigenschaftsnamen zu ändern, ohne zu wissen, dass die betreffende Klasse in ein Json-Objekt serialisiert wird. Wenn sie den Eigenschaftsnamen ändern, stellt die JsonProperty sicher, dass er im Json-Objekt und nicht im Eigenschaftsnamen verwendet wird.

arush436
quelle
3

Neben anderen Antworten ist die @JsonPropertyAnnotation sehr wichtig, wenn Sie die @JsonCreatorAnnotation in Klassen verwenden, die keinen Konstruktor ohne Argumente haben.

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 diesem Beispiel ist der einzige Konstruktor als markiert @JsonCreator, daher verwendet Jackson diesen Konstruktor, um die Instanz zu erstellen. Aber die Ausgabe ist wie folgt:

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

Ausnahme im Thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Instanz von ClassToSerialize $ MyEnum kann nicht aus dem Zeichenfolgenwert 'stringValue' erstellt werden: Wert nicht einer der deklarierten Enum-Instanznamen: [FIRST, SECOND, THIRD]

Aber nach dem Hinzufügen der @JsonPropertyAnnotation im Konstruktor:

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

Die Deserialisierung ist erfolgreich:

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

StringValue: ABCD

MyEnum: ZUERST

DVarga
quelle
2

Vergessen Sie neben all den obigen Antworten nicht den Teil der Dokumentation, der besagt

Markierungsanmerkung, mit der eine nicht statische Methode als "Setter" oder "Getter" für eine logische Eigenschaft (abhängig von ihrer Signatur) oder ein nicht statisches Objektfeld definiert werden kann, das als logisch verwendet (serialisiert, deserialisiert) werden soll Eigentum.

Wenn Sie non-staticin Ihrer Klasse eine Methode haben , die nicht konventionell getter or setterist, können Sie sie getter and settermithilfe der Annotation wie eine Methode verhalten. Siehe das folgende Beispiel

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

Wenn das obige Objekt serialisiert ist, enthält die Antwort

  • Benutzername von getUsername()
  • ID von getId()
  • idAndUsername von getIdAndUsername*

Da die Methode getIdAndUsernamemit getdann beginnt, wird sie als normaler Getter behandelt, weshalb Sie solche mit Anmerkungen versehen könnten @JsonIgnore.

Wenn Sie bemerkt haben, concatenateIdAndUsernamedass der Name nicht zurückgegeben wird und der Name nicht mit beginnt getund Sie möchten, dass das Ergebnis dieser Methode in die Antwort aufgenommen wird, können Sie es verwenden @JsonProperty("...")und es wird wie getter/setterin der oben hervorgehobenen Dokumentation erwähnt normal behandelt .

Raf
quelle
0

Von JsonProperty javadoc,

Definiert den Namen der logischen Eigenschaft, dh den Namen des JSON-Objektfelds, das für die Eigenschaft verwendet werden soll. Wenn der Wert leer ist, versucht String (dies ist die Standardeinstellung), den Namen des mit Anmerkungen versehenen Felds zu verwenden.

sc30
quelle