Have you tried the mappers constructType method?
Type genericType = User.class.getField("listProp").getGenericType();
List<Long> correctList = om.readValue(jsonEntry.getValue(), om.constructType(genericType));
Pergunta
Java erases normally the Generics
data on compilation, but there is a possibility to get that information (the Jackson ObjectMapper
does that pretty well).
My Problem: I have a Class with a property of List:
public class User {
public List<Long> listProp;//it is public only to keep the example simple
}
How can I get the correct TypeReference
(or JavaType
?) so that I can map programatically a JSON String to the correct List Type, having the instance of the Class
class (User.class) and the property name (listProp)? What I mean is this:
TypeReference typeReference = ...;//how to get the typeReference?
List<Long> correctList = om.readValue(jsonEntry.getValue(), typeReference);//this should return a List<Long> and not eg. a List<Integer>
Solução
Have you tried the mappers constructType method?
Type genericType = User.class.getField("listProp").getGenericType();
List<Long> correctList = om.readValue(jsonEntry.getValue(), om.constructType(genericType));
Outras dicas
jackson use TypeReference to construct generic type
TypeReference typeReference =new TypeReference<List<Long>>(){}
jackson use JavaType to construct generic type
JavaType jt = om.getTypeFactory().constructArrayType(Long.class);
jackson support three types
i like use JavaType, it is more clear for generic type, for normal object use Class
Perhaps a less exotic approach to deserializing a generic type is to wrap it inside a concrete type:
class ListLongWrapper extends ArrayList<Long> {} // package scope
... or ...
static class ListLongWrapper extends ArrayList<Long> {} // class scope
then
String jsonStr = objMapper.writeValueAsString(user1.listProp); // serialize
user2.listProp = objMapper.readValue(jsonStr,ListLongWrapper.class); // deserialize
Notice that extends
requires a class type (here I used ArrayList
) instead of the interface List
.
This suggests an even more direct approach for the given example -- User
is already a wrapper (and listProp
is public
):
public class User {
public List<Long> listProp;
}
then
String jsonStr = objMapper.writeValueAsString(user1); // serialize
var user2 = objMapper.readValue(jsonStr,User.class); // deserialize
In this case, you can use the interface List
as-is as a field type within the wrapping class, but this means you have no control over the concrete type that Jackson will use.