In a previous version of jackson (1.9.2), the following code worked fine:
import org.codehaus.jackson.map.JsonDeserializer; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.map.DeserializationContext; ... @JsonDeserialize(using = RoleDeserializer.class) public interface RoleDto {} public class RoleDeserializer extends SomeSharedDeserializer<RoleDto> {} public class SomeSharedDeserializer<T> extends JsonDeserializer<T> { @Override public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return jp.readValueAs(getImplementation()); } public Class<? extends T> getImplementation(){ ... returns some generated implementation of RoleDto } }
After we switched to the latest version of Jackson (1.9.13 provided by Wildfly 8.2), we got an exception:
com.fasterxml.jackson.databind.JsonMappingException: cannot create an instance of RoleDto, problem: abstract types either have to map to specific types, have a custom deserializer, or create additional type information
Well, as with the new jackson packages, we updated them to:
import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;
Now the deserializer is visible (there is no previous exception), however we get a StackOverflowError exception. The file com.fasterxml.jackson.databind.ObjectMapper reads the value (line 3023):
DeserializationContext ctxt = createDeserializationContext(jp, cfg); JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType); // ok, let get the value if (cfg.useRootWrapping()) { result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser); } else { result = deser.deserialize(jp, ctxt); }
We pass to the line: result = deser.deserialize(jp, ctxt);
As a result, it raises an infinite loop and a StackOverflowError.
One of the recommended methods is to implement our own SomeSharedDeserializer as:
ObjectCodec oc = jp.getCodec(); JsonNode node = oc.readTree(jp); //here manually create new object and return it
But our classes are generated. As another solution, I tried using
ObjectMapper mapper = new ObjectMapper(); mapper.readValue(jp, getImplementation());
But got the same result - StackOverflow exception.
How can we fix this? Is it possible to use some deserializer to pass its instance of JsonParser, a generated class that implements the base interface without StackOverflowError?