fastjson 泛型转换问题(详解)

系列文章目录

附属文章一:fastjson TypeReference 泛型类型(详解)



前言

本文讲解使用 fastjson 进行 json 转换泛型 T、泛型集合 R<List>、或者子类中的泛型、或者多层泛型,存在的 json 转换异常报错问题,以及解决方案。


一、代码演示

data 实际对象类型:

@Data
public class SysUser {

    String userId;

    String userName;
}

1. 不存在泛型转换

响应类:

@Data
public class R {

    Integer code;

    String msg;

    SysUser data;
}

测试类:


@Slf4j
public class Test {

    public static void main(String[] args) {
        String jsonStr = "{\"code\":0,\"msg\":\"操作成功\",\"data\":{\"userId\":\"1001\",\"userName\":\"小白\"}}";
        R rSysUser = JSONObject.parseObject(jsonStr, R.class);
        SysUser sysUser = rSysUser.getData();
        log.info("sysUser={}", sysUser.toString());
    }
}

执行上述代码,结果如下:

在这里插入图片描述

通过断点调试可以看到 JSONObject.parseObject(jsonStr, R.class) 转换后的对象中的子对象的实际类型为 SysUser,数据为等值的形式。

2. 存在泛型转换

泛型响应类:

@Data
public class R<T> {

    Integer code;

    String msg;

    T data;
}

泛型测试类:


@Slf4j
public class Test {

    public static void main(String[] args) {
        String jsonStr = "{\"code\":0,\"msg\":\"操作成功\",\"data\":{\"userId\":\"1001\",\"userName\":\"小白\"}}";
        R<SysUser> rSysUser = JSONObject.parseObject(jsonStr, R.class);
        SysUser sysUser = rSysUser.getData();
        log.info("sysUser={}", sysUser.toString());
    }
}

执行上述代码,结果如下:

在这里插入图片描述

通过断点调试可以看到 JSONObject.parseObject(jsonStr, R.class) 转换后的对象中的子泛型对象的实际类型为 JSONObject,数据为 key-value 的形式。

此时往下执行,进行 JSONObject 和 SysUser 对象的直接赋值,就会抛出异常:

在这里插入图片描述

3. 存在泛型集合转换

泛型集合测试类:


@Slf4j
public class Test {

    public static void main(String[] args) {
        String jsonStr = "{\"code\":0,\"msg\":\"操作成功\",\"data\":[{\"userId\":\"1001\",\"userName\":\"小白\"}]}";
        R<List<SysUser>> rSysUser = JSONObject.parseObject(jsonStr, R.class);
        List<SysUser> sysUserList = rSysUser.getData();
        log.info("sysUserList={}", sysUserList.toString());
        SysUser sysUser = sysUserList.get(0);
        log.info("sysUser={}", sysUser.toString());
    }
}

执行上述代码,结果如下:
在这里插入图片描述
通过断点调试可以看到 JSONObject.parseObject(jsonStr, R.class) 转换后的对象中的泛型集合对象的实际类型为 JSONObject,数据为 key-value 的形式。

此时往下执行,进行 JSONObject 和 SysUser 对象的直接赋值,就会抛出异常:
在这里插入图片描述

扩展:

当然,泛型 T、泛型集合 R<List>、或者子类中的泛型、或者多层泛型,都存在同样的问题。本文不再演示。

二、原因分析

因为当 json 转换的对象是泛型时,我们无法获取到实际的类,无法获取到类的变量,也无法获取到类变量的 get、set 方法,所以我们无法将这个 json 数据转换到某一个实际的类对象中存储,所以 com.alibaba.fastjson 会临时转换为 JSONObject 对象,以 key-value 形式存储。

这样就存在一个问题,当我们将该泛型对象赋值转换为实际的类对象时,就会因类型不匹配而抛出异常。

三、解决方案

1. 方案1:重新执行泛型的 json 转换

将泛型转换为 json 字符串后,重新进行类对象转换。

泛型转换:

R<SysUser> rSysUser = JSONObject.parseObject(jsonStr, R.class);
SysUser sysUser = JSONObject.parseObject(JSONObject.toJSONString(rSysUser.getData()), SysUser.class);

泛型集合转换:

R<List<SysUser>> rSysUser = JSONObject.parseObject(jsonStr, R.class);
List<SysUser> sysUserList = JSONObject.parseArray(JSONObject.toJSONString(rSysUser.getData()), SysUser.class);

2. 方案2:使用 TypeReference 指定泛型类型

使用 fastjson 的 TypeReference 来指定泛型类型。

在指定了 json 转换中泛型的实际类型后,就能获取到实际的类,获取到类的变量,获取到类变量的 get、set 方法,从而将泛型的 json 转换成实际的类对象。

本文不过多讲解 TypeReference 类,详细了解请转 《fastjson TypeReference 泛型类型(详解)》https://editor.csdn.net/md/?articleId=139363645

泛型转换:

R<SysUser> rSysUser = JSONObject.parseObject(jsonStr, new TypeReference<R<SysUser>>(){});
SysUser sysUser = rSysUser.getData();

泛型集合转换:

R<List<SysUser>> rSysUser = JSONObject.parseObject(jsonStr, new TypeReference<R<List<SysUser>>>(){});
List<SysUser> sysUserList = rSysUser.getData();

相关推荐

  1. json类型转换对象含有

    2024-06-08 04:12:03       50 阅读
  2. 【.NET Core】(Generics)详解

    2024-06-08 04:12:03       49 阅读
  3. C++ 模板和编程详解

    2024-06-08 04:12:03       29 阅读
  4. FastJson详解

    2024-06-08 04:12:03       20 阅读
  5. SpringBoot:对象存取与转换<JedisPool>

    2024-06-08 04:12:03       61 阅读
  6. <span style='color:red;'>泛</span><span style='color:red;'>型</span>..

    ..

    2024-06-08 04:12:03      61 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-08 04:12:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-08 04:12:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-08 04:12:03       87 阅读
  4. Python语言-面向对象

    2024-06-08 04:12:03       96 阅读

热门阅读

  1. Ansible语法与模块

    2024-06-08 04:12:03       32 阅读
  2. 从外部访问类中的私有成员

    2024-06-08 04:12:03       31 阅读
  3. kafka连接zookeeper失败导致无法启动

    2024-06-08 04:12:03       29 阅读