在序列化和反序列化的过程中,泛型是永远离不开的主题,那么泛型有哪几种呢?Jackson又是如何来处理这些问题的呢?
index | Name | Example |
---|---|---|
1 | ParameterizedType | 参数化类型,即泛型;例如:List、Map |
2 | TypeVariable | 类型变量,即泛型中的变量;例如:T、K、V等变量,可以表示任何类;在这需要强调的是,TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型 |
3 | GenericArrayType | 泛型数组类型,用来描述ParameterizedType、TypeVariable类型的数组;即List[] 、T[]等 |
4 | Class | Class是Type的一个实现类,属于原始类型,是Java反射的基础,对Java类的抽象 |
5 | WildcardType | 泛型表达式(或者通配符表达式),即? extend Number、? super Integer这样的表达式;WildcardType虽然是Type的子接口,但却不是Java类型中的一种 |
那么Jackson 是如何处理的呢?
public T readValue(JsonParser p, Class valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueType));
}
@Override
@SuppressWarnings("unchecked")
public T readValue(JsonParser p, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueTypeRef));
}
@Override
@SuppressWarnings("unchecked")
public final T readValue(JsonParser p, ResolvedType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), p, (JavaType) valueType);
}
public T readValue(JsonParser p, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), p, valueType);
}
最长接受的参数是:
class无需多说明,那么什么是JavaType,TypeReference呢?
在Jackson中可能是最终的类型吧,TypeReference最终还是会转化为JavaType,那么什么是JavaType呢?
Base class for type token classes used both to contain information and as keys for deserializers.
Instances can (only) be constructed by
com.fasterxml.jackson.databind.type.TypeFactory
.
Since 2.2 this implements {@link java.lang.reflect.Type} to allow
it to be pushed through interfaces that only expose that type.
用于包含信息和作为反序列化器的键的类型标记类的基类。只能通过TypeFactory来实例化。
通常的使用或者构造方式是:
1. 通过objectMapper.construct
JavaType javaType = JacksonConstant.OM.constructType(type);
2. 通过TypeProvier
JavaType javaType1 = TypeFactory.defaultInstance().constructType(type);
其实方式1本质上是2,源代码如下:
public JavaType constructType(Type t) {
//本质还是通过TypeFactory来实现的
return _typeFactory.constructType(t);
}
那么TypeFactory是如何实例化入参的呢?因为在反序列化的过程中,我们的入参是Type,但正如我们上面所述的,Type类包含了五个子类, Class, ParameterizedType, TypeVariable,WildCard,GenericArrayType,查看源码:
protected JavaType _fromAny(ClassStack context, Type type, TypeBindings bindings)
{
JavaType resultType;
// simple class?
if (type instanceof Class) {
// Important: remove possible bindings since this is type-erased thingy
resultType = _fromClass(context, (Class) type, EMPTY_BINDINGS);
}
// But if not, need to start resolving.
else if (type instanceof ParameterizedType) {
resultType = _fromParamType(context, (ParameterizedType) type, bindings);
}
else if (type instanceof JavaType) { // [databind#116]
// no need to modify further if we already had JavaType
return (JavaType) type;
}
else if (type instanceof GenericArrayType) {
resultType = _fromArrayType(context, (GenericArrayType) type, bindings);
}
else if (type instanceof TypeVariable) {
resultType = _fromVariable(context, (TypeVariable) type, bindings);
}
else if (type instanceof WildcardType) {
resultType = _fromWildcard(context, (WildcardType) type, bindings);
} else {
// sanity check
throw new IllegalArgumentException("Unrecognized Type: "+((type == null) ? "[null]" : type.toString()));
}
// 21-Feb-2016, nateB/tatu: as per [databind#1129] (applied for 2.7.2),
// we do need to let all kinds of types to be refined, esp. for Scala module.
if (_modifiers != null) {
TypeBindings b = resultType.getBindings();
if (b == null) {
b = EMPTY_BINDINGS;
}
for (TypeModifier mod : _modifiers) {
JavaType t = mod.modifyType(resultType, type, b, this);
if (t == null) {
throw new IllegalStateException(String.format(
"TypeModifier %s (of type %s) return null for type %s",
mod, mod.getClass().getName(), resultType));
}
resultType = t;
}
}
return resultType;
}
Jackson本身会根据类型来生成JavaType,记录相关的信息。
总结来说:JavaType,Jackson 自定义的一个记录入参Type的相关类的信息和其他和序列化相关的信息的类。
源码如下:
public abstract class TypeReference implements Comparable>
{
protected final Type _type;
protected TypeReference()
{
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public Type getType() { return _type; }
}
通用的使用方式是:
Map json2Map = JacksonConstant.OM.readValue(staffMapJson, new TypeReference
构建一个内部匿名类,名字是运行类下的$number,继承了TypeReference
getClass().getGenericSuperclass()
获取parameterizedType,类型为TypeReference,通过parameterizedType.getActualTypeArguments()[0],获取最终的类型:Map
这样的话就保留了需要的类型。
Staff staff1 = mapper.readValue(jsonInString, Staff.class);
//Pretty print
String prettyStaff1 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff1);
Object obj = JacksonConstant.OM.readValue(json, JacksonConstant.OM.constructType(type));
if (obj instanceof Staff) {
return (Staff) obj;
}
Map json2Map = JacksonConstant.OM.readValue(staffMapJson, new TypeReference
同理可得,对于List的反序列化可以推断为如下:
public static List json2List() throws IOException {
String json = "[{\"name\":\"rb.x\",\"age\":1,\"position\":\"sh\",\"salary\":100.23,\"skills\":[\"java\",\"mysql\"]}]";
//在反序列化为List的过程中,list 和Map本质上是parameterizedType
List staffList = JacksonConstant.OM.readValue(json, new TypeReference>() {
});
System.out.println(staffList.size());
return staffList;
}
可选:Jackson本身给了非常多的构造方法来满足不同的需求,
JacksonConstant.OM.getTypeFactory().constructXXXX()系列
具体可以看看源码
这里以list为例子:
public static List json2List2() throws IOException {
String json = "[{\"name\":\"rb.x\",\"age\":1,\"position\":\"sh\",\"salary\":100.23,\"skills\":[\"java\",\"mysql\"]}]";
//在反序列化为List的过程中,list 和Map本质上是parameterizedType
List staffList = JacksonConstant.OM.readValue(json, JacksonConstant.OM.getTypeFactory().constructCollectionType(List.class, Staff.class));
System.out.println(staffList.size());
return staffList;
}
constructCollectionType()实际返回的是JavaType的一个子类。
public static Map[] json2MapList() throws IOException {
String mapArrayJson = "[{\"id_1\":{\"name\":\"rb.x\",\"age\":1,\"position\":\"sh\",\"salary\":100.23,\"skills\":[\"java\",\"mysql\"]}}]";
Map[] mapArray = JacksonConstant.OM.readValue(mapArrayJson, JacksonConstant.OM.getTypeFactory()
.constructArrayType(JacksonConstant.OM.getTypeFactory().constructMapType(Map.class, String.class, Staff.class)));
System.out.println(mapArray[0].get("id_1").getName());
return mapArray;
}
其他如TypeVariable和wildCard的话就不举例了,因为遇到的太少了,如果遇到了再总结吧。
参考代码