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

问题描述 投票:7回答:2

我正在使用Jackson从JSON解组多态类型。我在@JsonTypeInfo使用类似于例4的@JsonSubTypes@JsonTypeNamethis post注释。我的问题是,现在说我需要其他人扩展我的代码并在原始代码库之外添加第三类:public class Duck extends Animal。如何(或其他人)添加子类型信息而不修改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 = "[email protected]"),  
    @Type(value = Dog.class, name = "[email protected]"),
    @Type(value = Catv2.class, name = "[email protected]")})
public abstract class Animal {
    ...
}

@JsonTypeName("[email protected]")
public class Cat extends Animal {
    ...
}

@JsonTypeName("[email protected]")
public class Catv2 extends Animal {
    ...
}

@JsonTypeName("[email protected]")
public class Dog extends Animal {
    ...
}

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

@JsonTypeName("[email protected]")
public class Dogv2 extends Animal {
    ...
}

现在我面临的问题是,如果不将@Type(value = another.zoo.Dogv2.class, name = "[email protected]")})添加到Animal类,我就无法解组具有类型名称“[email protected]”的JSON。因此,使用注释执行此操作显然是不可能的。有没有办法在运行时执行此操作?

更新2:

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

java jackson polymorphism deserialization unmarshalling
2个回答
4
投票

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


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,并不是一个非常可维护的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.