fastjson 泛型反序列化的诡异问题

查看 70|回复 3
作者:oneisall8955   
版本:fastjson 1.2.76
环境:springboot 2.3.6
问题概述:通过构造 TypeReference 实现泛型反序列化,但实际上序列化出来的并不是想要的实际类型。并且,只有在于线上的某个节点出现,且本地无法复现。
简化业务逻辑代码:
  • 泛型类 BaseResponse 装载通用的接口响应,其属性 private T data是不同类型的数据;
  • 普通类 CountryResponse 通过 json 数据反序列出:BaseResponse
  • 工具类 HttpRequestUtil,有个 static 方法将接口的 response body 反序列出 BaseResponse

        @Setter
        @Getter
        @ToString
        public static class BaseResponse {
            private Integer code;
            private String msg;
            private T data;
        }
       
        @Setter
        @Getter
        @ToString
        public static class CountryResponse {
            private String countryId;
            private String countryName;
        }
       
        public static class HttpRequestUtil {
            public static  List doGet4List(Class responseCls) {
                // 工具类方法,body 变量模拟了请求响应 {"code":0,"success":true,"msg":"success","data":[{"countryId":"CN","countryName":"China"}]}
                String body = "{\"code\":0,\"success\":true,\"msg\":\"success\",\"data\":[{\"countryId\":\"CN\",\"countryName\":\"China\"}]}";
                log.info("doGet4List result: [{}]", body);
                BaseResponse> baseResponse = JSON.parseObject(body, new TypeReference(responseCls) {
                });
                return Optional.ofNullable(baseResponse).map(BaseResponse::getData).orElse(null);
            }
        }
    问题报错代码
        @Test
        public void testFastJsonParse() {
            List countryResponses = HttpRequestUtil.doGet4List(CountryResponse.class);
            for (CountryResponse countryResponse : countryResponses) { // 这行报错了
                System.out.println(countryResponse.getCountryId());
            }
        }
    查看线上日志,报错行数是:for (CountryResponse countryResponse : countryResponses) { 这一行。
    java.lang.ClassCastException: class com.alibaba.fastjson.JSONObject cannot be cast to class com.foo.entity.CountryResponse(com.alibaba.fastjson.JSONObject and com.foo.entity.CountryResponse are in unnamed module of loader org.springframework.boot.loader.LaunchedURLClassLoader @2a2d45ba)
    猜测:countryResponses 这个 List 的元素实际上是 JSONObject 对象,遍历时候强转了一次。
    主要是线上的所有节点都是同样的镜像,只有某个节点会出这个错误,本地无法复现,拿相同的 json 数据去反序列,都能正确反序列出 CountryResponse 。这个工具类方法都跑了大半年了。。。
    自我怀疑人生 ing......

    private, Static, class, countryresponse

  • sumarker   
    我没太懂 BaseResponse> 这个里不是一个 list 吗? responseCls 不是 object.class 吗?
    oneisall8955
    OP
      
    @sumarker #1
    接口定义:public static  List doGet4List(Class responseCls) {... }
    接口调用:List countryResponses = HttpRequestUtil.doGet4List(CountryResponse.class);
    这里入参不是传递了 CountryResponse.class 了吗?
    另外,是不是上面例子用错了 api ,应该用 fastjson 的其他 api 来反序列化 BaseResponse?
    sumarker   
    @oneisall8955 #2
    我可能没说明白:
    1. 我记得 TypeReference 的用法是 在  里指明转换的类型
    2. 你的 BaseResponse 里写的是 List 但是你传入方法的是 CountryResponse.class ,我理解是 你的 T 是 CountryResponse ? 那你是要将 body 转成 BaseResponse ?
    所以我上面说没看懂你的意图 (另外 你的代码是 java 环境吧?)
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部