2013-09-05 35 views
43

Gson user guide tuyên bố rằng chúng ta nên định nghĩa hàm tạo không có giá trị mặc định cho bất kỳ lớp nào để làm việc với Gson đúng cách. Thậm chí nhiều hơn, trong các javadoc trên G23 của InstanceCreator lớp học nói rằng ngoại lệ sẽ được ném nếu chúng tôi cố gắng deserialize dụ của lớp thiếu constructor mặc định và chúng tôi nên sử dụng InstanceCreator trong trường hợp như vậy. Tuy nhiên, tôi đã cố gắng để thử nghiệm sử dụng Gson với lớp thiếu constructor mặc định và cả hai serialization và deserialization làm việc mà không có bất kỳ rắc rối.Công cụ xây dựng mặc định là no-args có bắt buộc đối với Gson không?

Đây là đoạn mã cho deserializaiton. Một lớp học mà không cần phi args constructor:

public class Mushroom { 
    private String name; 
    private double diameter; 

    public Mushroom(String name, double diameter) { 
     this.name = name; 
     this.diameter = diameter; 
    } 

    //equals(), hashCode(), etc. 
} 

và một bài kiểm tra:

@Test 
public void deserializeMushroom() { 
    assertEquals(
      new Mushroom("Fly agaric", 4.0), 
      new Gson().fromJson(
        "{name:\"Fly agaric\", diameter:4.0}", Mushroom.class)); 
} 

mà hoạt động tốt.

Vì vậy, câu hỏi của tôi là: Tôi có thể thực sự sử dụng Gson mà không cần phải có hàm tạo mặc định hoặc có bất kỳ hoàn cảnh nào khi nó không hoạt động không?

Trả lời

70

Kể từ Gson 2.3.1.

Bất kể tài liệu Gson nói gì, nếu lớp của bạn không có hàm khởi tạo no-arg và bạn chưa đăng ký bất kỳ đối tượng InstanceCreater, thì nó sẽ tạo một ObjectConstructor (xây dựng đối tượng của bạn) với UnsafeAllocator Phản ánh để có được phương thức allocateInstance của lớp sun.misc.Unsafe để tạo cá thể lớp của bạn.

Điều này Unsafe class đi xung quanh việc thiếu hàm tạo không có arg và có many other dangerous uses. allocateInstance tiểu bang

Phân bổ một thể hiện nhưng không chạy bất kỳ hàm tạo nào. Khởi tạo lớp nếu nó chưa được.

Vì vậy, nó không thực sự cần một hàm tạo và sẽ đi xung quanh hàm tạo hai đối số của bạn. Xem một số ví dụ here.

Nếu bạn có một constructor không có args, Gson sẽ sử dụng một ObjectConstructor trong đó sử dụng mặc định Constructor bằng cách gọi

yourClassType.getDeclaredConstructor(); // ie. empty, no-args 

2 cent Mỹ: Làm theo những gì Gson nói và tạo các lớp học của bạn với một không -arg constructor hoặc đăng ký InstanceCreator. Bạn có thể thấy mình ở vị trí không tốt bằng cách sử dụng Unsafe.

+0

Điều gì sẽ xảy ra nếu tôi có một hàm tạo mặc định để đặt thành viên cuối cùng của tôi thành null, nhưng không có setter cho thành viên này? Đó có phải là một giải pháp hợp lý không? –

+1

@ thomas.mc.work Gson sẽ có thể thiết lập trường trực tiếp thông qua sự phản chiếu (và có khả năng một số công việc không an toàn) và bạn có thể lấy nó thông qua một getter (hoặc trực tiếp thông qua hiện trường. Tôi không khuyên bạn nên thiết kế này. –

+0

I đã tìm thấy một giải pháp tốt cho vấn đề 'final' với jackson thư viện được mô tả ở đây: http://stackoverflow.com/a/11838468/2854723 –

1

Có một giải pháp tốt trong thư viện Jackson như đã mô tả ở đây:

https://stackoverflow.com/a/11838468/2854723

Vấn đề là để nói với serializer qua Mix-Ins feature mà JSON lĩnh vực sử dụng khi sử dụng các nhà xây dựng với các đối số.

Nếu thực thể đó là một phần của thư viện bên ngoài thì bạn có thể "chú thích từ xa" bằng Creator feature.

Các vấn đề liên quan