在用FastJson序列数据化转换时踩坑经验

之前一直是用Gson做数据序列化,后来换工作后新公司是用fastJson做序列化的,在做网络框架优化后,不定时的会抛出JsonObject can't covert to **** 异常,各种排查后发现是fastJson的问题,下面一步一步来分析:

原始json数据:

//登录前
{"code":200,"msg":"成功","data":[]}
//登录后
{"code":200,"msg":"成功","data":{"count":0}}

解析json代码:

static CommonResponse responseConvert(String json, Type clz){
           JSONObject object = new JSONObject(json);
           String data = object.optString(DATA);
           if(TextUtils.isEmpty(data) || "[]".equals(data) || "{}".equals(data) ){
            CommonResponse resp =  JSON.parseObject(json, CommonResponse.class);
           ....
           return resp;
           }else{
           return JSON.parseObject(json,clz)
           }
}

分析原因:

从代码上来看应该没问题,看不出什么问题,首先判断json的data字段是否为空或是否为空数组,如果是空则使用默认的CommonResponse类去解析,如果不为空则使用CommonResponse泛型的方式去解析,如果data字段一直为空或一直不为空都不会有问题,但如果从空变成有数据后就出现了上面的异常,通过查看fastJson源码才发现问题所在:
ParserConfig.Java

public ObjectDeserializer getDeserializer(Type type) {
     ...省略无关代码

      if (type instanceof Class) {
          return getDeserializer((Class) type, type);
      }
      if (type instanceof ParameterizedType) {
          Type rawType = ((ParameterizedType) type).getRawType();
          if (rawType instanceof Class) {
              return getDeserializer((Class) rawType, type);
          } else {
              return getDeserializer(rawType);
          }
      }
      return JavaObjectDeserializer.instance;
  }

通过源码可以看到,首先判断参数type是否为Class,如果是则进入getDeserializer方法,如果不是则继续判断参数是否为泛型,getRawType是获取泛型类型,如果泛型里面没有再嵌套泛型了则也进入getDeserializer方法,如果还有则进行递归调用,直到拿到最里面泛型为止,继续看getDeserializer方法:

public ObjectDeserializer getDeserializer(Class clazz, Type type) {
       ...省略无关代码
        if (type instanceof WildcardType || type instanceof TypeVariable || type instanceof ParameterizedType) {
            derializer = derializers.get(clazz);
        }

        if (derializer != null) {
            return derializer;
        }
        ...省略无关代码
        putDeserializer(type, derializer);
        return derializer;
 }

在getDeserializer方法中会先去判断缓存中是否已存储这个参数Class如果有则直接用缓存中的,如果没有则添加到缓存中。
 代码看到这里也就发现问题所在了,原因:首先在第一次解析CommonResponse的时候走的是getDeserializer的第一个if,然后缓存起来这个CommonResponse,接着在登录后,data字段数据类型发生了改变,变成CommonResponse类型,所以解析的走的是第二个if,结果rawType是CommonResponse,所以直接从缓存中返回了第一次解析的结果,这样就相当于丢失了CommonResponse中的泛型,所以导致最后类型转换失败!

总结

统一使用泛型类型,不允许没有泛型类型的CommonResponse,如果不能统一泛型类型的,最好换一个Json解析库!

你可能感兴趣的:(在用FastJson序列数据化转换时踩坑经验)