我有Jackson mixin和继承问题。我有两个目标类,父母和孩子。对于这两个目标类,我已经定义了两个没有继承关系的MixIn类(接口)。我还测试了一个MixIn接口扩展了另一个,但结果没有差异。当Jackson序列化父类时,它使用正确定义的mixin进行序列化配置,一切运行良好。但是,当Jackson序列化子类时,它将使用父类mixin定义来序列化父类和子类中存在的属性。然后,它使用子类mixin定义来序列化子类中定义的属性,但不在父类中定义。现在这可能与比较杰克逊的基类或实现接口有关。
现在的问题是,在序列化子类的对象时,有没有什么办法可以指示Jackson只使用子类的mixin定义?是的,我想保留两个单独的用例的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;
}
}
Mixins定义
public interface TestMixIn {
@JsonProperty("base-name")
public String getName();
}
public interface TestExtendMixIn {
@JsonProperty("ext-name")
public String getName();
@JsonProperty("ext-age")
public Integer getAge();
}
如果两个mixin都添加到mapper中,则输出JSON为:
{
"base-name": "5", // from parent class mixin definition
"ext-age": 50 // from child class mixin defition
}
使用mixin for 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'coinin处理的方法。对于上面的示例代码,这将意味着对TestExtendI接口的更改:
public interface TestExtendI extends TestI {
public Integer getAge();
// override the method from the parent interface here
@Override
public String getName();
}
这将解决问题,并且不会向解决方案添加太多样板代码。此外,它不会更改接口契约,因为子接口已经扩展了父接口。
答案 0 :(得分:7)
这是一个棘手的问题;您的具体问题的答案是否定的,您无法告诉子类不使用应用于父类的Mixin。
但是,这里解决您问题的一个简单方法是在TestExtendI接口中重新声明getName()
方法。我相信MixIn注释解析不遵循通常的父子覆盖(正常注释的情况),而是更喜欢应用于声明方法的类的MixIn。这可能是杰克逊的错误或设计选择,您可以随时填写github上的问题。