Tại sao khi một hàm tạo được chú thích bằng @JsonCreator, các đối số của nó phải được chú thích bằng @JsonProperty?


108

Trong Jackson, khi bạn chú thích một hàm tạo với @JsonCreator, bạn phải chú thích các đối số của nó với @JsonProperty. Vì vậy, hàm tạo này

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

trở thành cái này:

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

Tôi không hiểu tại sao nó lại cần thiết. Bạn có thể giải thích dùm không?

Câu trả lời:


112

Jackson phải biết thứ tự để chuyển các trường từ một đối tượng JSON đến phương thức khởi tạo. Không thể truy cập tên tham số trong Java bằng cách sử dụng phản chiếu - đó là lý do tại sao bạn phải lặp lại thông tin này trong các chú thích.


9
Điều này không hợp lệ cho Java8
MariuszS

12
@MariuszS Điều đó đúng nhưng bài đăng này giải thích cách loại bỏ các chú thích không liên quan với sự trợ giúp của cờ trình biên dịch Java8 và mô-đun Jackson. Tôi đã thử nghiệm cách tiếp cận và nó hoạt động.
quantum

Tất nhiên, hoạt động như một sự quyến rũ :) docs.oracle.com/javase/tutorial/reflect/member/…
MariuszS 21/09/15

52

Tên tham số thường không thể truy cập được bằng mã Java trong thời gian chạy (vì nó bị trình biên dịch bỏ qua), vì vậy nếu bạn muốn có chức năng đó, bạn cần sử dụng chức năng tích hợp của Java 8 hoặc sử dụng thư viện như ParaNamer để có quyền truy cập với nó.

Vì vậy, để không phải sử dụng chú thích cho các đối số của hàm tạo khi sử dụng Jackson, bạn có thể sử dụng một trong 2 mô-đun Jackson sau:

jackson-module-tham số-tên

Mô-đun này cho phép bạn nhận đối số phương thức khởi tạo không có chú thích khi sử dụng Java 8 . Để sử dụng nó, trước tiên bạn cần đăng ký mô-đun:

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

Sau đó, biên dịch mã của bạn bằng cờ -parameters:

javac -parameters ...

Liên kết: https://github.com/FasterXML/jackson-modules-java8/tree/master/parameter-names

jackson-module-paranamer

Cái khác này chỉ yêu cầu bạn đăng ký mô-đun hoặc định cấu hình phần nội quan chú thích (nhưng không phải cả hai như được chỉ ra bởi các nhận xét). Nó cho phép bạn sử dụng đối số phương thức khởi tạo không có chú thích trên các phiên bản Java trước 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());

Liên kết: https://github.com/FasterXML/jackson-modules-base/tree/master/paranamer


28

Có thể tránh các chú thích hàm tạo với jdk8 trong đó tùy chọn trình biên dịch sẽ giới thiệu siêu dữ liệu với tên của các tham số hàm tạo. Sau đó, với jackson-module-tham số-tên mô-đun Jackson có thể sử dụng hàm tạo này. Bạn có thể xem một ví dụ tại bài đăng Jackson mà không có chú thích


không dùng nữa và chuyển sang jackson-modules-java8 / tham số-tên
naXa

6

Bởi vì Java bytecode không giữ lại tên của các đối số phương thức hoặc hàm tạo.



1
@MariuszS thực sự, nhưng vì đây là một mới (và biên dịch lá cờ không phải mặc định), Jackson sẽ phải tiếp tục để hỗ trợ nó @JsonPropertychú thích
lcfd

6

Người ta có thể đơn giản sử dụng chú thích java.bean.ConstructorProperties - nó ít dài dòng hơn nhiều và Jackson cũng chấp nhận nó. Ví dụ :

  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

Khi tôi hiểu điều này một cách chính xác, bạn thay thế hàm tạo mặc định bằng một hàm được tham số hóa và do đó phải mô tả các khóa JSON được sử dụng để gọi hàm tạo với.


3

Như đã chuẩn bị trước trong tài liệu chú thích , chú thích chỉ ra rằng tên đối số được sử dụng làm tên thuộc tính mà không có bất kỳ sửa đổi nào, nhưng nó có thể được chỉ định thành giá trị không trống để chỉ định tên khác:


0

Chỉ cần xem qua nó và có câu trả lời ở đâu đó. bạn có thể sử dụng chú thích bên dưới kể từ 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;
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.