完美解决fastJson泛型多层级嵌套,类型转化错误

本文详细介绍了在使用fastJson时遇到的泛型多层级嵌套导致的类型转化错误问题,通过一步步的排查和学习,最终找到了解决办法。作者分享了关键的代码片段,并提醒了一个重要的调试注意事项。

完美解决fastJson泛型多层级嵌套,类型转化错误

先把实体类上了再说:

import lombok.Data;

@Data
public class Man {
    private String name;
    private String pass;

    public Man(String name, String pass) {
        this.name = name;
        this.pass = pass;
    }
}

然后把result结果封装类上了:

import lombok.Data;

/**
 * @author yangwulang
 */
@Data
public class Results<T> {
    private T data;
}

注意:我们一般会这样解析json数据

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author yangwulang
 */
public class Pp {
    public Results call(String jsons) {
        TypeReference<Results<Man>> typeReference = new TypeReference<Results<Man>>(s()) {};
        return JSON.parseObject(jsons, typeReference);
    }
}

但是写多了,就觉得很厌烦,然后会采用泛型,问题就来了在这里插入图片描述
我一般会这么写

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author yangwulang
 */
public class Pp<T> {
    public Results<T> call(String jsons) {
        TypeReference<Results<T>> typeReference = new TypeReference<Results<T>>() {};
        return JSON.parseObject(jsons, typeReference);
    }
}

然后就这么运行

import top.yangwulang.ge.Man;
import top.yangwulang.ge.Pp;
import top.yangwulang.ge.Results;
import java.util.List;

/**
 * Hello world!
 *
 * @author yangwulang
 */
public class AopTest {
    public static void main(String[] args) {
        Pp<List<Man>> listPp = new Pp<List<Man>>(){};
        Results<List<Man>> call = listPp.call("{\"data\":[{\"name\":\"aaa\",\"pass\":\"bb\"},{\"name\":\"2aa\",\"pass\":\"2bb\"}]}");
        call.getData().forEach(System.out::println);
    }
}

就会哦豁

Exception in thread "main" java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to top.yangwulang.ge.Man

的出现一个转换错误
这是为啥呢?上面写的不都没有出错吗?
经过一步步百度分析,问哥哥求姐姐的,找到了一篇博客
https://www.cnblogs.com/liqipeng/p/9148545.html
连接直接给大家贴上,点我直达
至于具体解析看博客,反正我是没太看懂他写的代码,但是在他博客里找到一句对我有用的代码

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

也就是这玩意,他的V5,原来这玩意可以传参,那我们试着读下FastJson源码:

/**
     * @since 1.2.9
     * @param actualTypeArguments
     */
    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 &&
                    actualIndex < actualTypeArguments.length) {
                argTypes[i] = actualTypeArguments[actualIndex++];
            }
            // fix for openjdk and android env
            if (argTypes[i] instanceof GenericArrayType) {
                argTypes[i] = TypeUtils.checkPrimitiveArray(
                        (GenericArrayType) argTypes[i]);
            }

            // 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
            if(argTypes[i] instanceof ParameterizedType) {
                argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
            }
        }

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

        type = cachedType;

    }

对,就是这段,顺着他的思想,老子直接就是穿个他两个参数List.class,Man.class这次不会报错了吧,(永远别这么想,你是摆脱不了墨菲定律的)还是报一样的错误,(sdfjalsdflashiofnsdklfXXXXXOOOOO),
大爷的,two days later,看着稀烂的代码,不还是要把他jiu(揪)过来,又是百度分析,这次不直接找fastJson了,劳资直接搜嵌套,不知从哪篇博客搜索出来的,((ParameterizedType) XXX.getClass().getGenericSuperclass()).getActualTypeArguments();就是这段可以获得里面的类型,刚刚好这个P返回的还是一个数组,结果就是你们知道的在这里插入图片描述
代码最终的形态是

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author yangwulang
 */
public class Pp<T> {

    public Results<T> call(String jsons) {
        TypeReference<Results<T>> typeReference = new TypeReference<Results<T>>(s()) {};
        return JSON.parseObject(jsons, typeReference);
    }
    //写不写方法都无所谓,最主要的是要拿到这个类上的类型
    public Type[] s(){
        return ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
    }
}

然后就没然后了,感谢大家的收看,结果给大家看下

E:\java\bin\java.exe -javaagent:E:\JBIDE\apps\IDEA-U\ch-0\193.6494.35\lib\idea_rt.jar=53687:E:\JBIDE\apps\IDEA-U\ch-0\193.6494.35\bin -Dfile.encoding=UTF-8 -classpath E:\java\jre\lib\charsets.jar;E:\java\jre\lib\deploy.jar;E:\java\jre\lib\ext\access-bridge-64.jar;E:\java\jre\lib\ext\cldrdata.jar;E:\java\jre\lib\ext\dnsns.jar;E:\java\jre\lib\ext\jaccess.jar;E:\java\jre\lib\ext\jfxrt.jar;E:\java\jre\lib\ext\localedata.jar;E:\java\jre\lib\ext\nashorn.jar;E:\java\jre\lib\ext\sunec.jar;E:\java\jre\lib\ext\sunjce_provider.jar;E:\java\jre\lib\ext\sunmscapi.jar;E:\java\jre\lib\ext\sunpkcs11.jar;E:\java\jre\lib\ext\zipfs.jar;E:\java\jre\lib\javaws.jar;E:\java\jre\lib\jce.jar;E:\java\jre\lib\jfr.jar;E:\java\jre\lib\jfxswt.jar;E:\java\jre\lib\jsse.jar;E:\java\jre\lib\management-agent.jar;E:\java\jre\lib\plugin.jar;E:\java\jre\lib\resources.jar;E:\java\jre\lib\rt.jar;D:\IDEAProject\spring-demo\demo-aop\target\classes;F:\apache\apache-maven-3.6.3\repository\org\projectlombok\lombok\1.16.8\lombok-1.16.8.jar;F:\apache\apache-maven-3.6.3\repository\org\springframework\spring-core\4.3.7.RELEASE\spring-core-4.3.7.RELEASE.jar;F:\apache\apache-maven-3.6.3\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;F:\apache\apache-maven-3.6.3\repository\org\springframework\spring-beans\4.3.7.RELEASE\spring-beans-4.3.7.RELEASE.jar;F:\apache\apache-maven-3.6.3\repository\org\springframework\spring-context\4.3.7.RELEASE\spring-context-4.3.7.RELEASE.jar;F:\apache\apache-maven-3.6.3\repository\org\springframework\spring-expression\4.3.7.RELEASE\spring-expression-4.3.7.RELEASE.jar;F:\apache\apache-maven-3.6.3\repository\org\springframework\spring-aop\4.3.7.RELEASE\spring-aop-4.3.7.RELEASE.jar;F:\apache\apache-maven-3.6.3\repository\org\springframework\spring-aspects\4.3.7.RELEASE\spring-aspects-4.3.7.RELEASE.jar;F:\apache\apache-maven-3.6.3\repository\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar;F:\apache\apache-maven-3.6.3\repository\com\alibaba\fastjson\1.2.49\fastjson-1.2.49.jar;F:\apache\apache-maven-3.6.3\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;F:\apache\apache-maven-3.6.3\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;F:\apache\apache-maven-3.6.3\repository\org\slf4j\slf4j-nop\1.7.25\slf4j-nop-1.7.25.jar top.yangwulang.AopTest
Man(name=aaa, pass=bb)
Man(name=2aa, pass=2bb)

Process finished with exit code 0

=======================================================
还有很重要的一步

搞得我调试了一下午。。。。。

public static void main(String[] args) {
        Pp<Man> pp = new Pp<Man>(){};
    }

这个对象必须得这样子new才能获得这个泛型!!!!!!!
当中俺还有有许多不正确的请大家指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值