简体   繁体   中英

How to get the Generic type for the Jackson ObjectMapper

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>

Have you tried the mappers constructType method?

Type genericType = User.class.getField("listProp").getGenericType();
List<Long> correctList = om.readValue(jsonEntry.getValue(), om.constructType(genericType));

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

  1. Class
  2. JavaType
  3. TypeReference

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM