2013-04-03 31 views
5

Tôi gặp vấn đề với mixin Jackson và thừa kế. Tôi có hai lớp mục tiêu, một phụ huynh và một đứa trẻ. Đối với hai lớp đích đó, tôi đã định nghĩa hai lớp MixIn (các giao diện) không có mối quan hệ thừa kế với nhau. Tôi cũng đã thử nghiệm với một giao diện MixIn mở rộng giao diện khác nhưng không có sự khác biệt về kết quả. Khi Jackson tuần tự hóa lớp cha, nó sử dụng mixin được định nghĩa chính xác cho cấu hình tuần tự hóa và mọi thứ hoạt động tốt. Tuy nhiên khi Jackson tuần tự hóa lớp con, nó sẽ sử dụng các định nghĩa mixin của lớp cha để tuần tự hóa các thuộc tính tồn tại trong cả lớp cha và lớp con. Sau đó, nó sử dụng các định nghĩa mixin của lớp con để tuần tự hoá các thuộc tính được định nghĩa trong lớp con nhưng không sử dụng trong lớp cha. Bây giờ điều này có thể có một cái gì đó để làm với việc so sánh các lớp cơ sở hoặc thực hiện các giao diện trong Jackson.Lựa chọn mixin Jackson và thừa kế

Bây giờ câu hỏi là có cách nào mà tôi có thể hướng dẫn Jackson chỉ sử dụng các định nghĩa mixin cho lớp con khi sắp xếp các đối tượng của lớp con không? Và có, tôi muốn giữ cả hai định nghĩa mixin tại chỗ cho hai trường hợp sử dụng riêng biệt, vì vậy chỉ cần loại bỏ ánh xạ mixin của lớp cha sẽ không giải quyết được vấn đề của tôi.

Mã ví dụ và JSON đầu ra được mong đợi và thực tế bên dưới.

Môi trường: Jackson phiên bản 2.1.4 Tomcat phiên bản 7.0.34.0

lớp Target và giao diện họ thực hiện:

public interface TestI { 

    public String getName(); 
} 


public interface TestExtendI extends TestI { 

    public Integer getAge(); 
} 


public class Test implements TestI { 

    String name; 

    public Test(String name) { 
    this.name = name; 
    } 

    @Override 
    public String getName() { 
    return name; 
    } 
} 

public class TestExtend extends Test implements TestExtendI { 

    private Integer age; 

    public TestExtend(String name) { 
    super(name); 
    } 

    public TestExtend(String name, Integer age) { 
    super(name); 
    this.age = age; 
    } 

    @Override 
    public Integer getAge() { 
    return age; 
    } 
} 

mixins các định nghĩa

public interface TestMixIn { 

    @JsonProperty("base-name") 
    public String getName(); 
} 


public interface TestExtendMixIn { 

    @JsonProperty("ext-name") 
    public String getName(); 

    @JsonProperty("ext-age") 
    public Integer getAge(); 
} 

Nếu cả hai mixins được thêm với người lập bản đồ, kết quả của JSON là:

{ 
    "base-name": "5", // from parent class mixin definition 
    "ext-age": 50  // from child class mixin defition 
} 

Với mixin cho TestI.class nhận xét mọi thứ hoạt động như mong đợi và đầu ra JSON là (đây là những gì tôi muốn đạt được):

{ 
    "ext-name": "5", // from child class mixin defition 
    "ext-age": 50  // from child class mixin defition 
} 

cấu hình đối tượng mapper

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
public class JacksonObjectMapper implements ContextResolver<ObjectMapper> { 

    private ObjectMapper mapper; 

    public JacksonObjectMapper() { 
    mapper = new ObjectMapper(); 
    mapper.addMixInAnnotations(TestI.class, TestMixIn.class); 
    mapper.addMixInAnnotations(TestExtendI.class, TestExtendMixIn.class);  
    } 

    public ObjectMapper getContext(Class<?> type) { 
    return this.mapper; 
    } 
} 

REST của api để xử lý yêu cầu/phản hồi

@Path("api/test/{id}") 
public class TestRestApi { 
    @GET 
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) 
    public TestI getTest(@PathParam("id") String id) { 

    TestI ret = new TestExtend(id, 50);  
    return ret; 
    } 
} 

Giải pháp

Như được mô tả bởi pgelinas trong phản ứng đầu tiên, giải pháp cho vấn đề này là xác định các phương pháp cần được xử lý bởi mixin 'con' một lần nữa trong giao diện con. Đối với mã ví dụ ở trên có nghĩa là các thay đổi đối với giao diện TestExtendI:

public interface TestExtendI extends TestI { 

    public Integer getAge(); 

    // override the method from the parent interface here 
    @Override 
    public String getName(); 
} 

Điều này sẽ giải quyết vấn đề và không thêm quá nhiều mã bản mẫu vào giải pháp. Hơn nữa nó sẽ không thay đổi các giao diện hợp đồng vì giao diện con đã mở rộng giao diện cha.

Trả lời

5

Đây là một điều khó khăn; câu trả lời cho câu hỏi cụ thể của bạn là không, bạn không thể yêu cầu một lớp con không sử dụng Mixin được áp dụng cho một lớp cha.

Tuy nhiên, giải pháp đơn giản cho vấn đề của bạn ở đây là khai báo lại phương thức getName() trong giao diện TestExtendI. Tôi tin rằng độ phân giải của chú thích MixIn không tuân theo ghi đè cha mẹ-con thông thường (như trường hợp với chú thích thông thường), nhưng thay vào đó, sẽ thích MixIn được áp dụng cho lớp khai báo phương thức. Đây có thể là lỗi trong Jackson hoặc lựa chọn thiết kế, bạn luôn có thể điền vào sự cố trên github.

+0

Cảm ơn, điều này thực sự hiệu quả. – user2239050

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