使Jackson子类型可扩展,而无需编辑Supertypes Java文件

时间:2019-04-29 08:43:20

标签: java spring-boot jackson jackson-databind

在我公司,我们有一个固定的JSON消息结构:

{
    "headerVal1": ""
    "headerVal2": ""
    "customPayload": {
        "payloadType":""
    }
}

我想拥有一种库,它使我不必关心公司定义的消息结构,而只是发送和接收有效载荷。

我的想法是,将公司模板的结构定义为一个对象,并使用PayloadObject的子类型。

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.MINIMAL_CLASS,
    property = "payloadType",
    visible = false)
public abstract class PayloadObject {
}

现在,我可以创建PayloadObject的子类,并且只要属性payloadType具有字符串".SubTypeName",就可以在此结构中自动反序列化。

这是有问题的,因为我无法自定义它,甚至一开始都没有删除多余的.。不幸的是,这不一定与公司现有的其他系统兼容,我们需要与之交互。

另一种方法是,添加一个@JsonSubTypes注释,在其中可以添加所有可能的子类型-在编写库时我不希望知道这些子类型。因此,此选项对我不起作用。

我认为,对子类型进行@JsonType注释可能会有所帮助,但是我仍然必须添加@JsonSubTypes,这无济于事。


  

有没有一种方法可以将子类型添加到基本类型而无需修改基本类型的Java文件?


如果这有帮助:我们正在使用Java Spring。

1 个答案:

答案 0 :(得分:0)

ObjectMapper具有方法registerSubtypes(NamedType),该方法可用于添加要使用的子类型,而不必将其包含在注释中。

为此,我创建了一个新的注释(我可能已经重用了@JsonTypeName,但它可能是滥用的)

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyJsonSubtype
{
   public String jsonTypeName();
}

然后我给我写了一个方法

public static void registerMyJsonSubtypes(ObjectMapper om, Object... reflectionArgs) {
    Reflections reflections = new Reflections(reflectionArgs);
    Set<Class<?>> types = reflections.getTypesAnnotatedWith(MyJsonSubtype.class);
    for (Class type : types) {
        String name = ((MyJsonSubtype) type.getAnnotation(MyJsonSubtype.class)).jsonTypeName();
        om.registerSubtypes(new NamedType(type, name));
    }
}

它使用Reflections获取在搜索包中声明的所有带注释的类型,并将它们注册为ObjectMapper的子类型。

这仍然需要基类上的@JsonTypeInfo注释将对象标记为可能可扩展,因此映射器知道使用哪个属性来解析名称,但是我想这是可以提供的。 我主要关注的问题是,我不想在基类的注释中声明所有将来的子类型。

  

尽管我是Java初学者,所以如果不需要或可能/应该/必须改进它,请分享您的想法。