温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

fastJson中怎么反序列化处理泛型

发布时间:2021-08-03 14:06:42 来源:亿速云 阅读:397 作者:Leah 栏目:大数据

fastJson中怎么反序列化处理泛型,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

都会的json解析

在我们日常的编码工作中,常常会制定或者遇到这样的json结构

{
  "resultcode": "200",
  "reason": "成功的返回",
  "result": {
    "area": "浙江省温州市平阳县",
    "sex": "男",
    "birthday": "1989年03月08日"
  }
}

对于该接口的提供者,最外层的resultcode reasonresult 这三个元素都是有的。因此我们可以定义一个这样的Response

public class Response<t> {
    private String resultcode;

    private String reason;

    private T result;

}

使用泛型来决定result最终向里面填充什么东西。当然,这里所填充的是一个对象,姑且我们也可以将它定义为User

public class User {
    private String area;
    private String sex;
    private String birthday;
}

这样,我们的数据就可以按照示例json的约定规则,返回给调用者了。 而作为调用方,也就是接收这条数据的机器,我们则需要定义如下的类ResopnseUser

public class ResopnseUser {
    private String resultcode;

    private String reason;

    private User result;
}

public class User {
    private String area;
    private String sex;
    private String birthday;
}

然后我们可以使用fastJson来进行愉快的解析了

        String  testJson = "{\"resultcode\":\"200\",\"reason\":\"成功的返回\",\"result\":{\"area\":\"浙江省温州市平阳县\",\"sex\":\"男\",\"birthday\":\"1989年03月08日\"}}";
        ResponseUser response1 =  JSONObject.parseObject(testJson,ResponseUser.class);

可以看到,也确实得到了我们想要的结果 fastJson中怎么反序列化处理泛型

思考改进措施

但是,这有个不太严重的后果。我每跟提供者对接一个接口,就得生成一个与之对应的类。久而久之,这些专用的类会变得越来越多,嵌套也会越来越深。既然提供者可以抽象出一个Response类,那么我是否也可以向提供者那样处理?

        String  testJson = "{\"resultcode\":\"200\",\"reason\":\"成功的返回\",\"result\":{\"area\":\"浙江省温州市平阳县\",\"sex\":\"男\",\"birthday\":\"1989年03月08日\"}}";
        Response<user> response =  JSONObject.parseObject(testJson,Response.class);

很遗憾,我们得到的结果并非所期望的,只有最外层的数据解析成功了,内层的result仍是JSONObject. fastJson中怎么反序列化处理泛型

求助于万能的论坛

幸运的事,在这万千工程师中并非只有想到了这种处理办法,并且已经有人解决这类问题了! 通过各种搜索下来,我们发现了fastJson提供了TypeReference这个类,可以解决我们的问题。

String  testJson = "{\"resultcode\":\"200\",\"reason\":\"成功的返回\",\"result\":{\"area\":\"浙江省温州市平阳县\",\"sex\":\"男\",\"birthday\":\"1989年03月08日\"}}";
        Response<user> response =  JSONObject.parseObject(testJson,new TypeReference<response<user>&gt;(){});

fastJson中怎么反序列化处理泛型 很好,我们已经得到了想要的结果,终于可以统一所有的接口最外层返回值的判断了。

绝不止步于此

等等,就没有发现什么问题吗?泛型在编译时会执行类型擦除啊!这也就是我们第一次直接使用Response<user> response = JSONObject.parseObject(testJson,Response.class);时无效的原因。 那么,即使我们这么写了new TypeReference<response<user>&gt;(){}不也一样会被擦除掉吗?运行时它是如何获取到我们所定义的实际类型的? 通过查看TypeReference的源码,幸运的是该源码十分的简单而且代码量少。首先进入的就是它的构造函数protected TypeReference(),通过debug我们发现,在代码执行到第二行时,就已经获得了我们所写的泛型.

        Type superClass = getClass().getGenericSuperclass();

        Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];

这段代码很简单,获取到它的父类getGenericSuperclass()就获取到了实际的类型.继续跟进代码,我们可以发现它调用了一个native方法private native String getGenericSignature0();获取到了该类和父类的一些信息ClassRepositoryType。 此时,回过头来我们再看new TypeReference<response<user>&gt;(){}其实是创建了一个TypeReference的匿名内部类,通过该类的getGenericSuperclass(),获取到了实际的类型信息。

继续深挖

让我们现在回顾一下我们的所得,注要有2点:

  1. 泛型在编译时会执行类型擦除

  2. 获取到它的父类getGenericSuperclass()就获取到了实际的类型。 等等,这两点是互相矛盾的啊。1说没有,2又说还能找到,到底是怎么回事呢?通过查看编译后的字节码文件,我们找到了答案。 fastJson中怎么反序列化处理泛型

这是包含代码Response<user> response = JSONObject.parseObject(testJson,new TypeReference<response<user>&gt;(){});的方法的class文件反编译后的信息。我们可以看到 它多了一个LocalvariableTypeTable,里面的Signature正好存储了实际的类型信息。**也就是说类型并未完全擦除,我们依然可以通过反射的方式拿到参数的类型。**所谓的擦除,只是把方法 code 属性的字节码进行擦除。 另外,我们还看到了InnerClasses列表中,有一个内部类,叫Main$1,也就是我们的这个new TypeReference<response<user>&gt;(){}

总结

  1. 可以通过JSONObject.parseObject(testJson,new TypeReference<response<user>&gt;(){});的方式,解决json中嵌套泛型的问题。方便、快捷、直观

  2. 可以通过getClass().getGenericSuperclass();获取到真实类型。验证代码

  // 这类创建了一个HashMap的匿名子类
        HashMap<string,integer> subIntMap = new HashMap<string,integer>(){};

        System.out.println(subIntMap.getClass().getSuperclass());

        Type subClassType = subIntMap.getClass().getGenericSuperclass();
        if(subClassType instanceof ParameterizedType){
            ParameterizedType p = (ParameterizedType) subClassType;
            for (Type t : p.getActualTypeArguments()){
                System.out.println(t);
            }
        }

输出结果

class java.util.HashMap
class java.lang.String
class java.lang.Integer
  1. 类型并未完全擦除,可以通过反射的方式拿到参数的类型。验证代码

 ResponseUser response = new ResponseUser();
        Field field = response.getClass().getField("result");
        System.out.println("result Type is "+ field.getType());
        System.out.println("result GenericType is "+ field.getGenericType());
public class ResponseUser {
    private String resultcode;

    private String reason;

    public List<user> result;
}

输出结果

result Type is interface java.util.List
result GenericType is java.util.List<com.jd.jr.alpha.cpa.fastjson.user>

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI