2013-04-03 27 views
5

我有一個問題,傑克遜混搭和繼承。我有兩個目標班,一個家長和一個孩子。對於這兩個目標類,我定義了兩個MixIn類(接口),它們之間沒有繼承關係。我還用一個MixIn接口進行了測試,擴展了另一個接口,但結果沒有差異。當傑克遜序列化父類時,它使用正確定義的mixin進行序列化配置,並且一切正常。但是,當Jackson序列化子類時,它將使用父類mixin定義序列化父類和子類中存在的屬性。然後它使用子類mixin定義來序列化在子類中定義的屬性,但不在父類中。現在這可能與在Jackson中比較基類或實現接口有關。傑克遜混搭的選擇和繼承

現在的問題是,有什麼方法可以指示Jackson在序列化子類的對象時僅使用子類的mixin定義?是的,我想保留兩個混合使用定義的兩個單獨的用例,所以只刪除父類mixin映射不會解決我的問題。

示例代碼以及下面的預期和實際輸出JSON。

環境: 傑克遜2.1.4版 Tomcat的版本號7.0.34.0

目標的類和接口它們實現:如果添加了兩個混入

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

混入定義

public interface TestMixIn { 

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


public interface TestExtendMixIn { 

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

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

到映射器的輸出JSON是:

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

由於混入了TestI.class評論說一切正常,輸出JSON是(這是我想什麼來實現):

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

對象映射配置

@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 api處理請求/響應

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

解決方案

正如pgelinas在第一個響應中所述,解決此問題的方法是定義child子接口中應該由'child'mixin處理的方法。對於上面的例子代碼就意味着更改TestExtendI接口:

public interface TestExtendI extends TestI { 

    public Integer getAge(); 

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

這將解決這個問題,並沒有太多的樣板代碼添加到解決方案。而且它不會改變接口契約,因爲子接口已經擴展了父接口。

回答

5

這是一個棘手的問題;你的具體問題的答案是否定的,你不能告訴孩子班級不要使用應用於父類的Mixin。

但是,這裏針對您的問題的簡單解決方案是在TestExtendI界面中重新聲明getName()方法。我相信MixIn註釋解決方案並不遵循通常的父子重寫(正常註釋的情況),而是更喜歡應用於聲明該方法的類的MixIn。這可能是傑克遜的一個bug或者是一個設計選擇,你總是可以在github上填寫一個問題。

+0

謝謝,這確實有效。 – user2239050