Mengapa ketika konstruktor dianotasi dengan @JsonCreator, argumennya harus dianotasi dengan @JsonProperty?


109

Di Jackson, saat Anda memberi anotasi pada konstruktor @JsonCreator, Anda harus memberi anotasi pada argumennya @JsonProperty. Jadi konstruktor ini

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

menjadi ini:

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

Saya tidak mengerti mengapa itu perlu. Bisakah Anda menjelaskan?

Jawaban:


113

Jackson harus mengetahui dalam urutan apa untuk meneruskan bidang dari objek JSON ke konstruktor. Tidak mungkin untuk mengakses nama parameter di Java menggunakan refleksi - itulah mengapa Anda harus mengulangi informasi ini dalam anotasi.


9
Ini tidak berlaku untuk Java8
MariuszS

12
@MariuszS Itu benar tetapi posting ini menjelaskan bagaimana menghilangkan anotasi asing dengan bantuan bendera compiler Java8 dan modul Jackson. Saya telah menguji pendekatannya dan berhasil.
kuantum


52

Nama parameter biasanya tidak dapat diakses oleh kode Java saat runtime (karena dijatuhkan oleh kompiler), jadi jika Anda menginginkan fungsionalitas itu, Anda perlu menggunakan fungsionalitas bawaan Java 8 atau menggunakan pustaka seperti ParaNamer untuk mendapatkan akses untuk itu.

Jadi agar tidak harus menggunakan anotasi untuk argumen konstruktor saat menggunakan Jackson, Anda dapat menggunakan salah satu dari 2 modul Jackson berikut:

jackson-module-parameter-names

Modul ini memungkinkan Anda mendapatkan argumen konstruktor bebas anotasi saat menggunakan Java 8 . Untuk menggunakannya, Anda harus mendaftarkan modul terlebih dahulu:

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

Kemudian kompilasi kode Anda menggunakan tanda -parameters:

javac -parameters ...

Tautan: https://github.com/FasterXML/jackson-modules-java8/tree/master/parameter-names

jackson-modul-paranamer

Yang lainnya ini hanya mengharuskan Anda untuk mendaftarkan modul atau mengkonfigurasi introspeksi anotasi (tetapi tidak keduanya seperti yang ditunjukkan oleh komentar). Ini memungkinkan Anda untuk menggunakan argumen konstruktor bebas anotasi pada versi Java sebelum 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());

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




6

Seseorang dapat dengan mudah menggunakan anotasi java.bean.ConstructorProperties - jauh lebih sedikit verbose dan Jackson juga menerimanya. Sebagai contoh :

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

4

Ketika saya memahami ini dengan benar, Anda mengganti konstruktor default dengan yang berparameter dan karena itu harus menjelaskan kunci JSON yang digunakan untuk memanggil konstruktor dengan.


3

Seperti yang dijelaskan sebelumnya dalam dokumentasi anotasi , anotasi tersebut menunjukkan bahwa nama argumen digunakan sebagai nama properti tanpa modifikasi apa pun, tetapi dapat ditentukan ke nilai yang tidak kosong untuk menentukan nama yang berbeda:


0

Temukan saja dan dapatkan jawaban di suatu tempat. Anda dapat menggunakan anotasi di bawah ini sejak 2.7.0

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class Point {
    final private double x;
    final private double y;

    @ConstructorProperties({"x", "y"})
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.