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>>>() {});
    }

这里使用的基于jsr-339标准的resteasy开发demo

浏览器访问: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 : 如果这里不知道我说的是什么,请调试的时候结合来看哈

最后也可以正确解析哈~

### 如何使用 FastJSON 进行 Java 对象的序列化 FastJSON 提供了多种方式来处理的序列化和反序列化。为了确保信息不丢失,在进行序列化操作时可以采用 `TypeReference` 或者通过显式指定类。 #### 使用 TypeReference 类安全地序列化与反序列化 对于复杂的数据结构,特别是带有参数的情况,推荐使用 `com.alibaba.fastjson.TypeReference` 来保持类的安全性和准确性。下面是一个具体的例子说明如何利用它来进行序列化: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; // 定义 Teacher 和 Student 类... public class Example { public static void main(String[] args) { // 创建一个包含列表的对象实例 Teacher<Student> teacher = new Teacher<>(); List<Student> students = Arrays.asList(new Student(1L, "Alice"), new Student(2L, "Bob")); teacher.setName("Mr. Smith"); teacher.setList(students); // 序列化为 JSON 字符串 String jsonString = JSON.toJSONString(teacher); System.out.println(jsonString); // 输出 JSON 表达形式 // 反序列化回原对象 TypeReference<Teacher<Student>> typeRef = new TypeReference<>() {}; Teacher<Student> deserializedTeacher = JSON.parseObject(jsonString, typeRef.getType()); // 验证结果 System.out.println(deserializedTeacher.getName()); for (Student student : deserializedTeacher.getList()) { System.out.printf("%s(%d)\n", student.getName(), student.getId()); } } } ``` 这段代码展示了完整的流程:创建了一个具有属性的对象并将其序列化成 JSON 文本;接着又从该文本恢复到原始对象状态而不会遇到任何类转换问题[^5]。 #### 显式提供 Class 对象作为类提示 另一种方法是在调用 `parseObject()` 方法时传入额外的 `Class<?>` 参数以指导反序列化进程。这种方式适用于简单的场景或者是已知确切的目标类的情形。 ```java // 假设我们有一个 Map<String, User> Map<String, User> userMap = ... ; String mapJsonStr = JSON.toJSONString(userMap); // 当我们知道目标是 HashMap 并且键值对分别是 String 和 User 的时候, // 就可以直接这样写: HashMap<String, User> parsedUserMap = JSON.parseObject(mapJsonStr, new HashMap<>(), String.class, User.class); ``` 这种方法虽然简单直观,但对于更复杂的嵌套则显得不够灵活[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值