-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Closed
Milestone
Description
Based on the following stack overflow question: http://stackoverflow.com/questions/29724859/jackson-deserialization-with-builder-pattern-build-method-has-bad-return-type
The builder deserailizer throws the "Build method has bad return type, not compatible with POJO type” exception if the build method return type is a super type of the POJO type. Here is a complete example:
public class JacksonBuilder {
public interface FooInterface {
}
public static class Foo implements FooInterface {
public static final class Builder {
@JsonProperty
public Builder valueA(String value) { return this; }
@JsonProperty
public Builder valueB(String value) { return this; }
public FooInterface build() { return new Foo() {}; }
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Foo.class, name = "foo")})
public static abstract class FooInterfaceMixin {}
@JsonTypeName("foo")
@JsonDeserialize(builder=Foo.Builder.class)
public static abstract class FooMixin {}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(FooInterface.class, FooInterfaceMixin.class);
mapper.addMixIn(Foo.class, FooMixin.class);
final String jsonString = "{\"type\":\"foo\", \"valueA\":\"a\", \"valueB\":\"b\"}";
FooInterface foo = mapper.readValue(jsonString, FooInterface.class);
}
}
Output:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Build method 'stackoverflow.JacksonBuilder$Foo$Builder#build(0 params) has bad return type (stackoverflow.JacksonBuilder$FooInterface), not compatible with POJO type (stackoverflow.JacksonBuilder$Foo)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:270)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:245)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:143)
at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:406)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:176)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:110)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:95)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:131)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:42)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3562)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2578)
at stackoverflow.JacksonBuilder.main(JacksonBuilder.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.IllegalArgumentException: Build method 'stackoverflow.JacksonBuilder$Foo$Builder#build(0 params) has bad return type (stackoverflow.JacksonBuilder$FooInterface), not compatible with POJO type (stackoverflow.JacksonBuilder$Foo)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder.buildBuilderBased(BeanDeserializerBuilder.java:378)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBuilderBasedDeserializer(BeanDeserializerFactory.java:297)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBuilderBasedDeserializer(BeanDeserializerFactory.java:155)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:351)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:265)
... 16 more
It seems that the condition at
jackson-databind/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
Line 377 in f757415
if (!valueType.getRawClass().isAssignableFrom(rawBuildType)) { |
!rawBuildType.isAssignableFrom(valueType.getRawClass())
to allow rawBuildType
be a super type of the valueType
.
Metadata
Metadata
Assignees
Labels
No labels