question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to make work TypeResolverBuilder with registerSubtypes

See original GitHub issue

Hello,

I can’t use annotations because it’s a external library so I neeed to register subTypes for an interface and set custom type handler.

I searched and tried multiple guides but without sucess

This is the code that I tried but without sucess, typeResolver is working but Jackson not matching the registered subTypes with the type.

TypeResolverBuilder<?> typeResolver = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL, BasicPolymorphicTypeValidator.builder()
                .allowIfBaseType(BeOutMessage.class)
                .build());
        typeResolver.init(JsonTypeInfo.Id.NAME, null);
        typeResolver.inclusion(JsonTypeInfo.As.PROPERTY);
        typeResolver.typeProperty("action");

        mapper.registerSubtypes(
                new NamedType(InitRequestBeMessage.class, ActionType.INIT_REQUEST.name()),
                new NamedType(PlayRequestBeMessage.class, ActionType.PLAY_REQUEST.name())
        );
        mapper.setDefaultTyping(typeResolver);

I get this error:

typecom.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'INIT_REQUEST' as a subtype of `classpath.BeOutMessage`: known type ids = []

The most easiest solution that I found is use JsonDeserializer:

public class BeOutMessageDeserializer extends JsonDeserializer<BeOutMessage> {

    @Override
    public BeOutMessage deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode jsonNode = p.getCodec().readTree(p);
        Class<? extends BeOutMessage> entityClass = BeOutMessageType.valueOf(jsonNode.get("action").asText()).entityClass();
        return ((ObjectMapper)p.getCodec()).readValue(jsonNode.toString(), entityClass);
    }
}
   

But I don’t like it and I don’t think that is efficient enough like the JsonSubTypes. How would be the proper way to do it at runtime?

Thank you!

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
xdrsynapsecommented, Jan 24, 2022

After some performance tests agaisnt mixin I got this results:

mixin:
Total execution time: 438ms
Total execution time: 217ms
Total execution time: 122ms
Total execution time: 183ms

customDeserializer:
Total execution time: 748ms
Total execution time: 370ms
Total execution time: 269ms
Total execution time: 336ms

And it improves a little bit when using with mapper.readerFor. Ergo we will use mixin and I hope that other devs can get usefull this issue for info.

Thanks @yawkat, I think we can close the issue if there is nothing else to add

0reactions
cowtowncodercommented, Jan 25, 2022

One note after the fact: if you use “Default Typing”, registration of subtypes has no effect – Default Typing specifically forces use of class names (and potentially opens up security holes). Subtype registration is (only) used when Type Ids are used instead – a safer approach, but one that does require mapping.

It sounds like mix-ins could work here, but use of TypeResolverBuilder would not make any sense to me.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Json deserialization into other class hierarchy using Jackson
You do then need to register subtypes (either by calling ObjectMapper.registerSubtypes() , or by using @JsonSubTypes annotation). – StaxMan. Apr ...
Read more >
Polymorphic resolution without annotations, looking for ...
Therefore my plan is to use a CustomTypeResolverBuilder to which I'm registering all subtypes in a generic way. What I have found so...
Read more >
ObjectMapper (jackson-databind 2.14.1 API) - javadoc.io
Overridable factory method, separate to allow format-specific mappers (and specifically XML-backed one, currently) to offer custom TypeResolverBuilder subtypes.
Read more >
TypeResolverBuilder (jackson-databind 2.9.0 API) - FasterXML
To create builders when "default typing" is used; if so, type information is automatically included for certain kind of types, regardless of annotations....
Read more >
Jackson - ObjectMapper Class - Tutorialspoint
It is also highly customizable to work both with different styles of JSON ... Customized TypeResolverBuilder that provides type resolver builders used with ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found