Make Jackson Subtypes extensible without editing the Supertypes java-file

£可爱£侵袭症+ 提交于 2021-02-08 05:29:20

问题


In my company we have a fixed JSON message structure:

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

I would like to have some kind of library, which allows me, to not care for the company defined message structure, and instead just send and receive the payload.

My idea was, to define the structure of the company template as one object, and use subtypes of a PayloadObject.

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

Now I can create subclasses of the PayloadObject, and it can be automatically deserialized in this structure, as long as the property payloadType has a string ".SubTypeName".

This is problematic, since I cannot customize it, not even remove the superflous . in the beginning. This is unfortunately not necessarily compatible with other, existing systems in the company, we need to interface with.

The alternative is, to add a @JsonSubTypes-annotation in which I can add all the possible subtypes - which I don't want to know when writing the library. So this option won't work for me.

I thought, it might help to have the @JsonType-annoation with the subtypes, but I still have to add the @JsonSubTypes, which does not help.


Is there a way, to add subtypes to a basetype without modifying the basetypes java-file?


If this helps: We are working with Java Spring.


回答1:


ObjectMapper has a method registerSubtypes(NamedType) which can be used to add subtypes for use, without having them in the annotations.

For this I created a new Annotation (I might have reused @JsonTypeName, but it might be abusive)

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

Then I wrote me a method

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));
    }
}

which uses Reflections to get all annotated types declared inside searched packages and registers them as subtypes for the ObjectMapper.

This still requires the @JsonTypeInfo-annotation on the base class to mark the object as potentially extensible, so the mapper knows, which property to use, to resolve the name, but I figure, this is is providable. My main attention was on the problem, that I don't want to declare all future subtypes in an annotation on the base class.

I am a Java beginner though, so please share your thoughts, if this is unnecessary or could/should/must be improved.



来源:https://stackoverflow.com/questions/55899757/make-jackson-subtypes-extensible-without-editing-the-supertypes-java-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!