Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoCtorDeser can not deserialize parameterized types #193

Open
luozhenyu opened this issue Jan 17, 2023 · 1 comment
Open

NoCtorDeser can not deserialize parameterized types #193

luozhenyu opened this issue Jan 17, 2023 · 1 comment

Comments

@luozhenyu
Copy link

Code

The following code throws java.lang.ClassCastException. The type of response.getPayload() is not User but LinkedHashMap

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.module.noctordeser.NoCtorDeserModule;

public class Demo {

    public static class Response<T> {

        private final T payload;

        public Response(T payload) {
            this.payload = payload;
        }

        public T getPayload() {
            return payload;
        }
    }

    public static class User {

        private final String name;

        public User(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    public static void main(String[] args) throws Exception {
        String json = "{\"payload\":{\"name\":\"jackson\"}}";
        JsonMapper mapper = JsonMapper.builder()
            .addModule(new NoCtorDeserModule())
            .build();

        ObjectReader objectReader = mapper.readerFor(new TypeReference<Response<User>>() {
        });
        Response<User> response = objectReader.readValue(json);
        System.out.println(response.getPayload().getClass());
    }
}

Cause

@cowtowncoder It seems the JsonDeserializer is fetched by Class<?> instClass rather than a ParameterizedType.

https://github.com/FasterXML/jackson-modules-base/blob/2.15/no-ctor-deser/src/main/java/com/fasterxml/jackson/module/noctordeser/MissingInstantiatorHandler.java#L34-L37

Solution

The overrided method DeserializationProblemHandler#handleMissingInstantiator(DeserializationContext ctxt, Class<?> instClass, ValueInstantiator valueInst, JsonParser jsonParser, String msg) does not suppy generic information. Maybe we can extend class AnnotatedWithParams and override its public abstract Object call() throws Exception;. Then we set it to the StdValueInstantiator's _defaultCreator field?

@cowtowncoder
Copy link
Member

In theory we could consider adding new version of handleMissingInstantiator() which takes JavaType (to retain generic type info). That seems like the way it could be done.
But that is called by handleMissingInstantiator() from DeserializationContext which would need to have overrides and delegation from old method as well, for backwards compatibility.

Although TBH, this module also uses a bit hacky way to go about construction as well. So maybe there could be different way that would not rely on having to find deserializer.

Not sure if AnnotatedWithParams route would be feasible; I guess one wouldn't need to get full deserializer if we could get ValueInstantiator to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants