Kapan properti @JsonProperty digunakan dan untuk apa properti itu?

183

Kacang ini 'Negara':

public class State {

    private boolean isSet;

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

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

}

dikirim melalui kawat menggunakan callback 'sukses' ajax:

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

Apakah penjelasan @JsonProperty diperlukan di sini? Apa keuntungan menggunakannya? Saya pikir saya dapat menghapus anotasi ini tanpa menimbulkan efek samping.

Membaca tentang anosi ini di https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations Saya tidak tahu kapan ini harus digunakan?

langit biru
sumber

Jawaban:

238

Ini contoh yang bagus. Saya menggunakannya untuk mengubah nama variabel karena JSON berasal dari .Netlingkungan di mana properti dimulai dengan huruf besar.

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

Ini dengan benar mem-parsing ke / dari JSON:

"Parameter":{
  "Name":"Parameter-Name",
  "Value":"Parameter-Value"
}
OldCurmudgeon
sumber
1
Bisakah variabel anggota String tidak diubah namanya menjadi kasus yang benar, jadi publik nama String; menjadi Nama String publik; ?
langit biru
14
Ya mereka bisa, tetapi di lingkungan Java yang membuat mereka tidak cocok dengan standar pengkodean. Ini lebih tentang keangkuhan saya bahwa masalah pengkodean nyata tetapi ini adalah contoh yang baik namun sederhana dari penggunaan nyata @JsonPropertyanotasi.
OldCurmudgeon
Bisakah anotasi ini digunakan untuk anggota tipe Double? Saya hanya ingin tahu apakah jenisnya harus Stringatau jenis apa saja yang didukung JSON? Mungkinkah itu tipe apa pun? @OldCurmudgeon
Dreamer
3
@Dreamer Ya. Tipe ini tidak relevan. Ini hanya memengaruhi namanya .
OldCurmudgeon
1
@Pavan - Itu tidak ada hubungannya dengan penamaan. Saya kira Anda harus memeriksa setter Anda.
OldCurmudgeon
44

Saya pikir OldCurmudgeon dan StaxMan keduanya benar tetapi di sini adalah satu jawaban kalimat dengan contoh sederhana untuk Anda.

@JsonProperty (nama), memberitahu Jackson ObjectMapper untuk memetakan nama properti JSON ke nama bidang Java yang dianotasi.

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

//where it gets mapped 
public static class Car {
  @JsonProperty("Type")
  public String type;
 }
grepit
sumber
Apakah nama Class harus sama dengan elemen root JSON. Ini tidak bekerja untuk saya.
Pavan
39

nah untuk apa nilainya sekarang ... JsonProperty juga JUGA digunakan untuk menentukan metode pengambil dan penyetel untuk variabel selain serialisasi dan deserialisasi biasa. Misalnya anggap Anda memiliki muatan seperti ini:

{
  "check": true
}

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

Maka dalam hal ini penjelasan JsonProperty diperlukan. Namun jika Anda juga memiliki metode di kelas

public class Check {

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

  public Boolean getCheck() {
     return check;
  }
}

Lihat juga dokumentasi ini: http://fasterxml.github.io/jackson-annotations/javadoc/2.3.0/com/fasterxml/jackson/annotation/JsonProperty.html

Richeek
sumber
15

Tanpa anotasi, nama properti yang disimpulkan (untuk mencocokkan dari JSON) akan menjadi "set", dan tidak - seperti yang tampaknya menjadi maksud - "isSet". Ini karena sesuai spesifikasi Java Beans, metode bentuk "isXxx" dan "setXxx" diambil untuk berarti bahwa ada properti logis "xxx" untuk dikelola.

StaxMan
sumber
1
Yang ini adalah jawaban yang benar untuk kasus khusus yang diberikan dalam pertanyaan
Andrew Spencer
6

Seperti yang Anda tahu, ini semua tentang cerita bersambung dan desalinize objek. Misalkan ada objek:

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

Serialisasi objek ini adalah:

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

Nama variabel langsung digunakan untuk membuat serialisasi data. Jika Anda akan menghapus api sistem dari implementasi sistem, dalam beberapa kasus, Anda harus mengganti nama variabel dalam serialisasi / deserialisasi. @JsonProperty adalah data meta untuk memberi tahu serializer cara objek serial. Ini digunakan untuk:

  • nama variabel
  • akses (BACA, TULIS)
  • nilai default
  • diperlukan / opsional

dari contoh:

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
sumber
6

Menambahkan JsonProperty juga memastikan keamanan jika seseorang memutuskan mereka ingin mengubah salah satu nama properti yang tidak menyadari kelas yang dimaksud akan diserialisasi ke objek Json. Jika mereka mengubah nama properti, JsonProperty memastikan itu akan digunakan dalam objek Json, dan bukan nama properti.

arush436
sumber
3

Selain jawaban lain, @JsonPropertyanotasi sangat penting jika Anda menggunakan @JsonCreatoranotasi di kelas yang tidak memiliki konstruktor 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);
    }
}

Dalam contoh ini satu-satunya konstruktor ditandai sebagai @JsonCreator, oleh karena itu Jackson akan menggunakan konstruktor ini untuk membuat instance. Tetapi hasilnya seperti:

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

Pengecualian di utas "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Tidak dapat membuat instance dari ClassToSerialize $ MyEnum dari nilai String 'stringValue': nilai bukan salah satu dari nama contoh Enum yang dinyatakan: [FIRST, SECOND, THIRD]

Tetapi setelah penambahan @JsonPropertyanotasi dalam konstruktor:

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

Deserialisasi berhasil:

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

StringValue: ABCD

MyEnum: PERTAMA

DVarga
sumber
2

Selain semua jawaban di atas, jangan lupa bagian dari dokumentasi yang mengatakan

Anotasi penanda yang dapat digunakan untuk mendefinisikan metode non-statis sebagai "setter" atau "pengambil" untuk properti logis (tergantung pada tanda tangannya), atau bidang objek non-statis yang akan digunakan (serial, deserialized) sebagai logis Properti.

Jika Anda memiliki non-staticmetode di kelas Anda yang tidak konvensional getter or settermaka Anda dapat membuatnya bertindak seperti getter and setterdengan menggunakan anotasi di atasnya. Lihat contoh di bawah ini

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

Ketika objek di atas diserialisasi, maka respons akan berisi

  • nama pengguna dari getUsername()
  • id dari getId()
  • idAndUnama pengguna dari getIdAndUsername*

Karena metode ini getIdAndUsernamedimulai dengan getmaka itu diperlakukan sebagai pengambil normal maka, mengapa Anda bisa membuat anotasi dengan@JsonIgnore .

Jika Anda perhatikan bahwa concatenateIdAndUsernameitu tidak dikembalikan dan itu karena namanya tidak dimulai getdan jika Anda ingin hasil metode itu dimasukkan dalam respons maka Anda dapat menggunakan @JsonProperty("...")dan itu akan diperlakukan seperti biasa getter/settersebagaimana disebutkan dalam dokumentasi yang disorot di atas. .

Raf
sumber
0

Dari JsonProperty javadoc,

Menentukan nama properti logis, yaitu nama bidang objek JSON untuk digunakan untuk properti. Jika nilai String kosong (yang merupakan default), akan mencoba menggunakan nama bidang yang dianotasi.

sc30
sumber