在Jackson中,我使用注释 @JsonTypeInfo 来包含多态支持。
如果,我不想使用基于注释的方法,我可以使用全局默认键入或覆盖类型信息处理模块。
我尝试了全局类型信息,但它为所有非最终类型发出了类型信息。
我需要什么,
仅通过扭曲全局配置是否有可能达到以上两点?
如果没有,我应该用什么扩展点来定制类型信息模块? 我读过 JacksonAnnotationIntrospector 是处理类型信息的类。
我应该自定义它以达到上述两点吗?
帮助示例将会很好。
答案 0 :(得分:7)
你可以使用杰克逊的DefaultTypeResolverBuilder
来达到这个目的。扩展此类并适当地覆盖useForType
方法。下面是一个仅为属于test.jackson
包(和子包)的类添加类型信息的示例:
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTypeResolverBuilder;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
public class CustomTypeResolverBuilder extends DefaultTypeResolverBuilder
{
public CustomTypeResolverBuilder()
{
super(DefaultTyping.NON_FINAL);
}
@Override
public boolean useForType(JavaType t)
{
if (t.getRawClass().getName().startsWith("test.jackson")) {
return true;
}
return false;
}
}
现在,请考虑Foo.java
包中的test.jackson
和Bar.java
包中的org.myorg
,每个包含一个名为“整数”的int
变量和一个String
变量名为“string”。
您可以通过这种方式序列化这两个类的对象:
ObjectMapper objectMapper = new ObjectMapper();
TypeResolverBuilder<?> typeResolver = new CustomTypeResolverBuilder();
typeResolver.init(JsonTypeInfo.Id.CLASS, null);
typeResolver.inclusion(JsonTypeInfo.As.PROPERTY);
typeResolver.typeProperty("@CLASS");
objectMapper.setDefaultTyping(typeResolver);
Foo foo = new Foo(10, "Foo");
Bar bar = new Bar(20, "Bar");
System.out.println(objectMapper.writeValueAsString(foo));
System.out.println(objectMapper.writeValueAsString(bar));
相应的输出将是:
{"@CLASS":"test.jackson.Foo","integer":10,"string":"Foo"}
{"integer":20,"string":"Bar"}
您还可以自定义表示类型的属性的名称(上例中的“@CLASS”)。希望这有帮助!
答案 1 :(得分:0)
您可以使用Moonwlker库。
有了它,您可以像这样创建ObjectMapper
:
ObjectMapper objectMapper = new ObjectMapper();
MoonwlkerModule module =
MoonwlkerModule.builder()
.fromProperty("@CLASS").toSubclassesOf(Animal.class)
.build();
objectMapper.registerModule(module);
然后使用该映射器进行(反)序列化。 Moonwlker网站包含更多详细信息和配置选项。