I’ve seen plenty of examples of how to deal with Jackson deserialization when using abstract classes and generics, but I’m trying to understand why type inference isn’t possible in certain cases. Consider the following:
Objects:
public abstract class BaseObject {
public String someField;
}
public class ConcreteObjectOne extends BaseObject {}
public class ConcreteObjectTwo extends BaseObject {}
Classes deserializing objects:
public abstract class BaseService<T extends BaseObject> {
public T deserializeObjectFail(String json) throws JsonProcessingException {
var mapper = JsonMapper.builder().build();
return mapper.readValue(json, new TypeReference<T>() {});
}
public T deserializeObjectSuccess(String json, TypeReference<T> typeReference) throws JsonProcessingException {
var mapper = JsonMapper.builder().build();
return mapper.readValue(json, typeReference);
}
}
public class ConcreteServiceOne extends BaseService<ConcreteObjectOne> {}
public class ConcreteServiceTwo extends BaseService<ConcreteObjectTwo> {}
Tests:
var serviceOne = new ConcreteServiceOne();
var serviceTwo = new ConcreteServiceTwo();
// These fail with an InvalidDefinitionException
serviceOne.deserializeObject("{"someField":"one"}");
serviceTwo.deserializeObject("{"someField":"two"}");
// These succeed
serviceOne.deserializeObjectFixed("{"someField":"one"}", new TypeReference<>() {});
serviceTwo.deserializeObjectFixed("{"someField":"two"}", new TypeReference<>() {});
Why does the first example fail while the second succeeds? It seems like the generic type should be known in both cases. The class definitions of ConcreteServiceOne
and ConcreteServiceTwo
provide the concrete object types that T
represents.
So shouldn’t new TypeReference<T>() {}
be able to make use of the types provided for T
by the concrete classes? Why would that fail, while using TypeReference<T>
as a parameter provided by the concrete classes work even when the concrete classes are using type inference by passing in new TypeReference<>() {}
? It seems like the type of T
should be able to be inferred equally in both cases, especially considering the generic type can even be omitted in the second example.