In der vorherigen Version von Jackson (1.9.2) der folgende Code hat gut funktioniert:REST Jackson JsonDeserialize, Stackoverflow nach Upgrade
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 }
}
Nachdem wir in den letzten jackson Version (1.9.13 von Wildfly bereitgestellt migriert 8.2) bekamen wir eine Ausnahme:
com.fasterxml.jackson.databind.JsonMappingException: nicht Instanz RoleDto, Problem konstruieren kann: abstrakte Typen müssen entweder konkrete Typen zugeordnet werden, benutzerdefinierte Deserializer haben oder sein instanziiert mit zusätzliche Typinformationen
Ok, wie in neue Pakete jackson verwendet werden, aufgerüstet wir sie:
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;
Der Deserializer jetzt sichtbar ist (die vorhergehende Ausnahme ist weg), Aber wir bekommen StackOverflowError-Ausnahme Der com.fasterxml.jackson.databind.ObjectMapper liest Wert (Linie 3023):
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
// ok, let's get the value
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
} else {
result = deser.deserialize(jp, ctxt);
}
Wir sind auf die Linie gehen: result = deser.deserialize(jp, ctxt);
Es bewirkt Endlosschleife und Stackoverflow als Ergebnis.
Einer der Art und Weise, die empfohlen wird, ist unsere eigenen SomeSharedDeserializer zu implementieren:
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
//here manually create new object and return it
Aber unsere Klassen erzeugt werden. Als eine andere Lösung habe ich versucht,
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(jp, getImplementation());
zu verwenden, aber das gleiche Ergebnis - StackOverflow Ausnahme.
Wie können wir es beheben? Können wir einen Deserializer verwenden, um die JsonParser-Instanz zu übergeben, eine generierte Klasse, die die Basisschnittstelle implementiert, und ohne StackOverflowError?