1. 程式人生 > >Fastjson解析多級泛型的幾種方式—新增使用class檔案來解析多級泛型

Fastjson解析多級泛型的幾種方式—新增使用class檔案來解析多級泛型

Fastjson解析多級泛型

前言

現在網上大多數是使用TypeReference 方式來解析JSON資料,這裡我提供另外一種方式來解析,使用類檔案進行解析,兩種方式我都會給出實際程式碼

例項

TypeReference方式
    @GET
    @Path("getUserCourse")
    @Produces(MediaType.APPLICATION_JSON)
    public Result<List<UserCourseDto>> getUserCourse(){
        return externalBiz.getUserCourse();
    }
public Result<List<UserCourseDto>> getUserCourse(){
        String result = restTemplate.getForObject(MOCK_JSON_URL, String.class);
        return JSONObject.parseObject(result, new TypeReference<Result<List<UserCourseDto>>>() {});
    }

瀏覽器訪問:http://localhost:8080/v1/province/getUserCourse

可以得到json返回的結果

{
  status: 0,
  message: "1",
  data: [
    {
      openType: "兌換 ",
      userID: 30014,
      classID: 10376,
      className: "趣味職場俚語課程【11月班】",
      chargeFee: 106,
      classStudyTime: null,
      openRMB: 0,
      rechargeFee: 0,
      awardFee: 0,
      openFee: 0,
      dateAdded: 1312175789393,
      expiredDate: 1323964800000
    }
  ]
}

介紹:

這裡使用了提供的TypeReference進行包裝,能夠清晰明瞭進行解析多級泛型,但是有時候,我們做一些通用的解析框架的時候,可能會用T型別,T型別拿到的是位元組碼檔案,或者class物件,又該怎麼處理呢?請看下面介紹。

class類方式

介面:

介面之類用了一個註解來處理的,沒有直接傳class物件過去,因為在實際專案中,基本都是註解,沒有誰會直接傳class物件。所以我傳的Annotation陣列過去啦

    @GET
    @Reader(extParamClass = {Result.class,List.class,UserCourseDto.class})
    @Path("getUserCourseV2")
    @Produces(MediaType.APPLICATION_JSON)
    public Result<List<UserCourseDto>> getUserCourseV2(){
        Annotation[] annotations = new Annotation[0];
        for (Method method : this.getClass().getMethods()) {
            if (method.getName().equals("getUserCourseV2")){
                annotations = method.getAnnotations();
            }
        }
        return externalBiz.getUserCourseV2(annotations);
    }

處理:

public Result<List<UserCourseDto>> getUserCourseV2(Annotation[] annotations) {
        final Reader[] readers = {null};
        if(annotations != null) {
            Arrays
                    .stream(annotations)
                    .filter(annotation -> annotation.annotationType().equals(Reader.class))
                    .findFirst().ifPresent(x -> readers[0] = (Reader) x);
        }
        Class[] classes = readers[0].extParamClass();
        String result = restTemplate.getForObject(MOCK_JSON_URL, String.class);
        //這裡不用TypeReference方式,直接用class物件來處理

        ParameterizedTypeImpl beforeType = null;
        if (classes.length!=0){
            //支援多級泛型的解析
            for (int i = classes.length-1; i >0 ; i--) {
                beforeType = new ParameterizedTypeImpl(new Type[]{beforeType == null? classes[i]:beforeType}, null, classes[i - 1]);
            }
        }
        return  JSON.parseObject(result,beforeType);
}

程式碼評析:

主要起作用的還是這兩行程式碼

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

主要意思是將你的class物件包裝成一個ParameterizedTypeImpl,使用ParameterizedTypeImpl來解析多級泛型,但是要注意的是,每層泛型,都需要用一個ParameterizedTypeImpl物件進行包裝起來才會起作用,因為他會有一個actualTypeArguments 和一個 rawType ,在多級泛型中,用我這裡的例子說明,第一層的時候rawType 會是一個Result物件,而actualTypeArguments 會是一個包裝過後的ParameterizedTypeImpl物件,第二層的時候,rawType 會是一個List物件,而actualTypeArguments 會是包裝上一層的物件。後同。PS : 如果這裡不知道我說的是什麼,請除錯的時候結合來看哈

最後也可以正確解析哈~

END