Java 使用Jackson for多态性在运行时添加子类型信息

Java 使用Jackson for多态性在运行时添加子类型信息,java,jackson,polymorphism,deserialization,unmarshalling,Java,Jackson,Polymorphism,Deserialization,Unmarshalling,我正在使用Jackson从JSON中解组多态类型。我正在使用类似于中示例4的@JsonTypeInfo、@JsonSubTypes和@JsonTypeName注释。我的问题是,假设现在我需要其他人来扩展我的代码并添加第三个类:公共类Duck extends Animal,在原始代码库之外。我(或其他人)如何在不修改公共抽象动物类的源代码(注释)的情况下添加子类型信息 更新: 我被迫使用@JsonTypeName来解决POJO版本的更改。例如: package my.zoo; @JsonTypeI

我正在使用Jackson从JSON中解组多态类型。我正在使用类似于中示例4的
@JsonTypeInfo
@JsonSubTypes
@JsonTypeName
注释。我的问题是,假设现在我需要其他人来扩展我的代码并添加第三个类:
公共类Duck extends Animal
,在原始代码库之外。我(或其他人)如何在不修改
公共抽象动物类的源代码(注释)的情况下添加子类型信息

更新:

我被迫使用@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”的JSON。dog@2.0“不添加
@Type(value=other.zoo.Dogv2.class,name=”my.zoo。Dog@2.0)
动物类。因此,使用注释进行此操作显然是不可能的。有没有办法在运行时做到这一点

更新2:


我刚刚发现了相同/相似的用例。我在这里担心的是,使用注释会阻止人们扩展/实现基类/接口。我想要一种方法来保持我的基类/接口的可扩展性,并确保我的(非)编组逻辑将与未来的具体类型一起工作。

不要使用
@JsonSubTypes
。与一起使用可标识序列化和反序列化的类型

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
abstract class Animal { /* whatever */ }
然后Jackson将存储完全限定的名称来序列化对象,并再次使用它来确定反序列化的目标类

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
abstract class Animal { /* whatever */ }
您必须确保所有子类都没有名为
type
的属性



使用
@JsonSubTypes
可以实现这一点,但它涉及混合,不是一个非常可维护的解决方案。

我最终使用反射库查找
动物类的所有子类型,并使用
映射器注册JsonSubTypes.registerSubtypes(class…class)
方法

谢谢你的提示!但是,我不得不使用@JsonTypeName(“”)注释,就像更新的示例中一样。有没有办法处理这个问题?@SotiriosDelimanolis是的,但这样你仍然需要在json文本中传递完整的类名(即{“type”:“my.class”,“data”:{…})。对吗?@ampofila在这个设置中,是的。还有更多选择。谢谢您的及时回复。我来看看。您可以在类型属性名称中使用大写字母,例如“type”,以确保没有类会用另一个属性重写此属性,至少在它符合Java命名约定的情况下是这样。您对@JsonTypeInfo注释做了什么?是否使用了JsonTypeInfo.Id.NAME?@ampofila,模型代码如示例代码所示。这个在引导过程中,在应用程序驱动程序中进行了RegisterSubtypes()调用。在反序列化json时,Jackson会处理好一切。感谢您的及时回复。但是,我不知道如何拦截REST服务(我有一个控制器,它将接口作为param,并自动取消对入站json的marshall处理)。当我从文件中读取某些内容时,您的方式是有效的,但它不适合使用REST的POST请求。@ampofila,抱歉,但我在这方面没有经验。@derrdji您能提供一个如何使用
mapper.registerSubtypes