使用Jackson获取多态性,在运行时添加SubType信息

时间:2015-12-04 00:48:54

标签: java jackson polymorphism deserialization unmarshalling

我正在使用Jackson从JSON解组多态类型。我在this post中使用了类似于示例4的@JsonTypeInfo@JsonSubTypes@JsonTypeName注释。我的问题是,现在说我需要其他人来扩展我的代码并在原始代码库之外添加第3类:public class Duck extends Animal。我如何(或其他人)添加SubType信息而不修改public abstract Animal class的源代码(注释)?

更新:

我被迫使用@JsonTypeName来解决POJO版本更改。例如:

package my.zoo;
@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "type")  
@JsonSubTypes({  
    @Type(value = Cat.class, name = "my.zoo.cat@1.0"),  
    @Type(value = Dog.class, name = "my.zoo.dog@1.0"),
    @Type(value = Catv2.class, name = "my.zoo.cat@2.0")})
public abstract class Animal {
    ...
}

@JsonTypeName("my.zoo.cat@1.0")
public class Cat extends Animal {
    ...
}

@JsonTypeName("my.zoo.cat@2.0")
public class Catv2 extends Animal {
    ...
}

@JsonTypeName("my.zoo.dog@1.0")
public class Dog extends Animal {
    ...
}

// in another java package/project
package another.zoo;
import my.zoo.*;

@JsonTypeName("my.zoo.dog@2.0")
public class Dogv2 extends Animal {
    ...
}

现在我遇到的问题是我无法解组具有类型名称" my.zoo.dog@2.0"的JSON。没有将@Type(value = another.zoo.Dogv2.class, name = "my.zoo.Dog@2.0")})添加到Animal类。因此,使用注释执行此操作显然是不可能的。有没有办法在运行时执行此操作?

更新2:

我刚发现this SO question具有相同/相似的用例。我担心的是使用注释会阻止人们扩展/实现你的基类/接口。我想要一种方法来保持我的基类/接口的可扩展性,并确保我的(un)编组逻辑将适用于未来的具体类型。

2 个答案:

答案 0 :(得分:4)

我最终使用Reflections库查找Animal类的所有子类型,并使用mapper.registerSubtypes(Class<?>... classes)方法注册JsonSubTypes。

答案 1 :(得分:1)

请勿使用@JsonSubTypes。使用@JsonTypeInfo#useJsonTypeInfo.Id.CLASS标识序列化和反序列化的类型。

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
abstract class Animal { /* whatever */ }

Jackson将存储完全限定名称以序列化对象并再次使用它来确定反序列化的目标类。

您必须确保没有子类具有名为type的属性。

可以使@JsonSubTypes使用它,但它涉及mixins,并不是一个非常易于维护的解决方案。