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

Provided TypeReference doesn't enable deserialization of an object with generic constructor #254

Closed
l15k4 opened this issue Jul 1, 2013 · 4 comments

Comments

@l15k4
Copy link

l15k4 commented Jul 1, 2013

Model:

public class AgentResponse<T> {

    private T result;
    private ResponseStatus status;

    public AgentResponse(T result, ResponseStatus status) {
        this.result = result;
        this.status = status;
    }
    public T getResult() {
        return result;
    }
    public ResponseStatus getStatus() {
        return status;
    }
}

public class ResponseStatus {

    private Boolean succeeded;
    private String message;

    public ResponseStatus(Boolean succeeded, String message) {
        this.succeeded = succeeded;
        this.message = message;
    }
    public Boolean getSucceeded() {
        return succeeded;
    }
    public String getMessage() {
        return message;
    }
}

Input Json:

{"result":{"first-client-id":3,"test-mail-module":3,"third-client-id":3,"second-client-id":3},"status":{"succeeded":true,"message":"OK"}}
mapper.readValue(out, new TypeReference<AgentResponse<Map<String, Integer>>>() {});

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.fg.mail.smtp.AgentResponse<java.util.Map<java.lang.String,java.lang.Integer>>]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: java.io.InputStreamReader@4f2d26d2; line: 1, column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:984)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2064)

@l15k4
Copy link
Author

l15k4 commented Jul 1, 2013

jackson-databind version 2.2.2

@l15k4
Copy link
Author

l15k4 commented Jul 1, 2013

Actually even using javaType it throws the same error:

JavaType javaType = mapper.getTypeFactory().constructParametricType(AgentResponse.class, Map.class);
mapper.readValue(out, javaType);

@l15k4
Copy link
Author

l15k4 commented Jul 1, 2013

SOLVED: I didn't know that I have to use @JsonCreator and @JsonProperty("result") annotations ... I was debugging the jackson stack all the way down and I saw it found the constructor arguments, so I thought it was the generics problem. In fact the real problem was that jackson couldn't know the constructor argument names cause JVM doesn't provide it. Damn I should have try that without generics first...

@l15k4 l15k4 closed this as completed Jul 1, 2013
@cowtowncoder
Copy link
Member

Correct: @JsonCreator is needed to indicate which constructor to use, and @JsonProperty for names.

Except that if you want to get by without second part, you can try to use this module:

https://github.com/FasterXML/jackson-module-paranamer

which uses Paranamer lib to dig up parameter names, which are included in bytecode for debugging, unless explicitly removed. You still need to use @JsonCreator (although maybe removing the need would be a nice feature for Paranamer module? I think that'd be doable actually -- you can file an issue for that project if you like).

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