FreeBuilder
FreeBuilder copied to clipboard
Jackson deserializes generic parameter using default deserializer
Here is the test code:
package test;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.io.IOException;
import org.inferred.freebuilder.FreeBuilder;
@FreeBuilder
@JsonDeserialize(builder = GenericType.Builder.class)
interface GenericType<T> {
T getValue();
//@JsonCreator
//static <T> GenericType of(@JsonProperty("value") T value) {
// return new GenericType.Builder<>().setValue(value).build();
//}
class Builder<T> extends GenericType_Builder<T> {}
}
public class Test {
public static void main(String[] args) throws IOException {
String json = "{\"value\": \"123\"}";
ObjectMapper objectMapper = new ObjectMapper();
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(
GenericType.class,
Long.class);
GenericType<Long> object = objectMapper.readValue(json, javaType);
System.out.println(object.getValue().getClass());
}
}
If you run it, it should result in Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
.
However changing deserialization from @JsonDeserialize(builder = GenericType.Builder.class)
to static @JsonCreator
seems to solve the problem, but ideally we don't want to write this manually.
It is worth noting that using String json = "{\"value\": 123}";
result in java.lang.Integer
being deserialized instead of java.lang.Long
. So it looks like Jackson is picking up some default deserialization method (String for JSON String, Integer for JSON Number) instead of trying to deserialize into custom type. It is especially annoying if you try to use StringWrapper-like classes.
Tested with jackson 2.4.4 and 2.6.5.
It seems to be caused by https://github.com/FasterXML/jackson-databind/issues/921
I suggest maybe generating @JsonCreator
code to fix this issue? It will also get rid of @JsonDeserialize
.
Thanks for the investigative work, @divath! I'll leave this as an open "upstream bug" for reference, but I don't think we should be working around open Jackson bugs. (That said, if you release a FreeBuilder fix and commit to maintaining it, that's a different matter 😉 )