JSON是一种轻量级的数据交换格式。其简洁明了的层次结构使JSON成为一种理想的数据交换语言,在实际项目中经常被使用。Java生态中有很多处理JSON格式化的类库,比如json-lib框架,Jackson,谷歌的Gson,阿里的FastJson等,通过这些类库,我们可以更方便的处理JSON。下面这篇文章主要通过一个实际案例来探讨和分析在解析JSON字符串的过程中如何处理泛型。案例描述问题介绍解决方案原理分析1.案例描述首先介绍三个类,为了便于理解,省略了非关键部分的代码。PrepCommonResp是一个通用的响应类。为了支持多种返回类型,将其中一个属性result设置为generic。publicclassPrepCommonResp{privateTresult;//获取调用返回值privateStringcode="000000";//获取错误码privateStringmsg="Success";//这里省略gettersetter等}LeaderboardResp是一个Leaderboard接口响应类,一个其中是一个List集合中的对象是LeaderboardPojopublicclassLeaderboardRespimplementsSerializable{ListleaderboardList;//这里省略gettersetter等}LeaderboardPojo是一个实体类publicclassLeaderboardPojo{//基本属性}需求:解析String类型的数据一个JSON字符串到指定的Generic泛型响应类实例PrepCommonResp对象。2.问题介绍写作之初,使用了Jackson的ObjectMapper类的readValue方法进行分析。具体代码如下。ObjectMappermapper=newObjectMapper();PrepCommonRespresp=mapper.readValue(result,PrepCommonResp.class);我们期望的结果是JSON字符串被正确解析,并且result属性的值以指定的通用LeaderboardResp的格式存储。但是过了断点后,我们发现result属性的值是以LinkedHashMap的形式存储的,与预期的结果不符。三、解决方法在分析原因之前,先说说解决方法。有很多解决方案。对比了各种方案,我们选择了一种比较简单的,就是用Gson的fromJson方法来解决。具体代码如下://尝试使用GsonGsongson=newGson();PrepCommonRespresp=gson.fromJson(result,newTypeToken>(){}.getType());Listlist=resp.getResult().getLeaderboardList();我们期望LeaderboardResp形式存储4.原理分析1.首先了解泛型和编译虚拟机的关系,什么是擦除?分析:Java语言的泛型基本都是在编译器中实现的。编译器进行类型检测和推理生成普通的非泛型字节后,虚拟机完全不知道泛型的存在。这种实现技术称为擦除。编译器使用通用类型信息来确保类型安全,然后在生成字节码之前对其进行清理。2、为什么使用Jackson的readValue方法解析JSON字符串后结果的属性值为LinkedHashMap,而不是我们指定的LeaderboardResp?分析:泛型只在编译时起到检测作用,当编译器完成对泛型类的编译后,泛型类的类型参数全部被擦除。其次,虚拟机在运行过程中并不知道泛型的存在。在解析JSON字符串的时候,因为泛型被抹掉了,所以虚拟机不知道要解析成哪种类型,所以解析为默认的LinkedHashMap类型,导致了上面的场景。3、Gson如何解决泛型擦除的情况?我们来看看这段核心代码PrepCommonRespresp=gson.fromJson(result,newTypeToken>(){}.getType());分析:Gson的方法很巧妙。如上代码所示,将需要获取类型的泛型类作为TypeToken的泛型参数构造一个匿名子类,然后我们通过getType()方法获取即可。所需泛型类的泛型参数类型。可以理解为保存泛型是为了解决泛型擦除的问题。5.最后,感谢您的阅读。如果您喜欢本文,请关注并转发。本头条号会继续分享IT技术知识。如果您对文章内容有其他的想法或建议,欢迎大家一起讨论,共同进步。如果你对这个场景有更好的解决方案,欢迎大家一起讨论。