fastjson反序列化多层嵌套泛型类


1、在使用SpringMVC时,通常会定义通用类型与前端进行交互

@Data
public class Result<T> {
    private int ret;
    private String msg;
    private T data;
}

定义一个需要迭代的对象

@Data
public class Item {
    private String name;
    private String value;
}

2、将下列json数据转化为一个Result<Item>对象

{
    "data":{
	"name":"username",
	"value":"root"
    },
    "msg":"Success",
    "ret":0
}

2.1、错误转化方法

// 方法1-编译器就报错了Cannot select parameterized type。
JSONObject.parseObject(json, Result<Item>.class);

// 方法2-执行没问题。但是没有Item类型信息,fastjson不可能跟你心有灵犀一点通知道该把data转为Item类型
SONObject.parseObject(json, Result.class);

2.2、正确转化方法

/**
 * 将上述的Json串转化为对象
 */
private static <T> Result<T> parseResultV1(String json) {
    return JSONObject.parseObject(json, new TypeReference<Result<T>>() {});
}

3、针对Result泛型进行动态的转化

3.1、错误方法

// java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to Item
private static <T> Result<T> parseResultV1(String json) {
    return JSONObject.parseObject(json, new TypeReference<Result<T>>() {});
}

3.2、正确的方法

TypeReference的构造器是可以传入参数的,

private static <T> Result<T> parseResultV2(String json, Class<T> clazz) {
    return JSONObject.parseObject(json, new TypeReference<Result<T>>(clazz) {});
}

4、针对Result<List>泛型进行动态的转化

4.1、TypeReference的源码

protected TypeReference(Type... actualTypeArguments) {
    Class<?> thisClass = this.getClass();
    Type superClass = thisClass.getGenericSuperclass();
    ParameterizedType argType = (ParameterizedType)((ParameterizedType)superClass).getActualTypeArguments()[0];
    Type rawType = argType.getRawType();
    Type[] argTypes = argType.getActualTypeArguments();
    int actualIndex = 0;

    for(int i = 0; i < argTypes.length; ++i) {
        if (argTypes[i] instanceof TypeVariable) {
            argTypes[i] = actualTypeArguments[actualIndex++];
            if (actualIndex >= actualTypeArguments.length) {
                break;
            }
        }
    }

    Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
    Type cachedType = (Type)classTypeCache.get(key);
    if (cachedType == null) {
        classTypeCache.putIfAbsent(key, key);
        cachedType = (Type)classTypeCache.get(key);
    }

    this.type = cachedType;
}

4.2、自己封装

TypeReference无法处理嵌套的泛型(这里指的是类型参数未确定,而不是类似Result<List<Item>>类型参数已经确定)。借用Fastjson解析多级泛型的几种方式—使用class文件来解析多级泛型里的方法,新增加一个专门处理List类型的方法:

/**
  * 方法1:针对多个的情况
  */
private <T> Result<List<T>> parseListResult(String json, Class<T> clazz) {
    return JSONObject.parseObject(json, buildType(Result.class, List.class, Item.class));
}

private Type buildType(Type... types) {
    if (types == null && types.length == 0) {
        return null;
    }

    ParameterizedTypeImpl beforeType = null;
    if (types.length == 1) {
        beforeType = new ParameterizedTypeImpl(null, null, types[0]);
        return beforeType;
    }

    for (int i = types.length - 1; i > 0; i--) {
        beforeType = new ParameterizedTypeImpl(
                  new Type[]{beforeType == null ? types[i] : beforeType}, null, types[i - 1]);
    }
    return beforeType;
}

/**
 * 方法2:针对Result<List<T>>这种情况
 */
private static <T> Result<List<T>> parseListResult(String json, Class<T> clazz) {
    ParameterizedTypeImpl inner = new ParameterizedTypeImpl(new Type[]{clazz}, null, List.class);
    ParameterizedTypeImpl outer = new ParameterizedTypeImpl(new Type[]{inner}, null, Result.class);
    return JSONObject.parseObject(json, outer);
}

原创文章,作者:745907710,如若转载,请注明出处:https://blog.ytso.com/270841.html

(0)
上一篇 2022年6月30日
下一篇 2022年6月30日

相关推荐

发表回复

登录后才能评论