Specific ordering of type information for polymorphic deserialization
steveme opened this issue · 3 comments
steveme commented
Hi,
Encountering the following problem with jackson-module-afterburner:2.6.1where the class attribute has to be after the polymorphic value in deserialization.
Succeeds:
{"payload":{"something":"test"},"class":"Payload"}
Throws exception below:
{"class":"Payload","payload":{"something":"test"}}
com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing property 'payload' (expected type: [simple type, class java.lang.Object]; actual type: Payload), problem: Can not set java.lang.Object field Envelope.payload to com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import org.junit.Test;
import java.io.IOException;
class Envelope {
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "class")
private Object payload;
public Envelope(@JsonProperty("payload") Object payload) {
this.payload = payload;
}
@JsonProperty
public Object getPayload() {
return payload;
}
}
class Payload {
private String something;
public Payload(@JsonProperty("something") String something) {
this.something = something;
}
@JsonProperty
public Object getSomething() {
return something;
}
}
public class AfterBurnerTest {
@Test
public void testAfterburner() throws IOException {
String successCase = "{\"payload\":{\"something\":\"test\"},\"class\":\"Payload\"}";
String failCase = "{\"class\":\"Payload\",\"payload\":{\"something\":\"test\"}}";
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new AfterburnerModule());
Envelope envelope1 = mapper.readValue(successCase, Envelope.class);
Envelope envelope2 = mapper.readValue(failCase, Envelope.class);
}
}
The exception:
com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing property 'payload' (expected type: [simple type, class java.lang.Object]; actual type: Payload), problem: Can not set java.lang.Object field Envelope.payload to com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer
at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:546)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.set(FieldProperty.java:128)
at com.fasterxml.jackson.databind.deser.CreatorProperty.set(CreatorProperty.java:201)
at com.fasterxml.jackson.databind.deser.CreatorProperty.deserializeAndSet(CreatorProperty.java:180)
at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler._deserializeAndSet(ExternalTypeHandler.java:253)
at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler.handlePropertyValue(ExternalTypeHandler.java:119)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeUsingPropertyBasedWithExternalTypeId(BeanDeserializer.java:792)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:716)
at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserializeFromObject(SuperSonicBeanDeserializer.java:234)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:131)
at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserialize(SuperSonicBeanDeserializer.java:117)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3702)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2714)
at AfterBurnerTest.testAfterburner(AfterBurnerTest.java:49)
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:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
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:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Object field Envelope.payload to com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:764)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.set(FieldProperty.java:126)
... 38 more
cowtowncoder commented
Sounds like a bug. Thank you for reporting this.
cowtowncoder commented
Seems to also affect 2.5.
cowtowncoder commented
I suspect the real culprit is the one from databind; with that fix, Afterburner test passes.