JSON是一种轻量级的数据交换格式,简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言,常被用于实际项目中。下面本文主要通过一个实际案例讨论分析在解析JSON字符串的过程中遇到泛型该如何处理。
JSON是一种轻量级的数据交换格式,简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言,常被用于实际项目中。Java生态圈中有很多处理JSON格式化的类库,如json-lib框架、Jackson、Google的Gson、阿里的FastJson等,通过这些类库可以使我们更加简便地处理JSON。下面本文主要通过一个实际案例讨论分析在解析JSON字符串的过程中遇到泛型该如何处理。
一、案例描述
首先介绍三个类,为了便于理解将代码省去非关键部分。
需求:将一个JSON字符串的String类型数据解析到指定了泛型的通用响应类实例PrepCommonResp对象中。
二、问题引出
一开始编写时,采用了Jackson的ObjectMapper类readValue方法来进行解析,具体代码如下。
我们期待的结果是JSON字符串被正确解析,并且result属性的值是以指定泛型LeaderboardResp的格式存储。但是通过断点之后我们发现result属性的值是以LinkedHashMap的形式存储,与期望结果不符。
三、解决方案
在分析原因之前,先来说说解决方式。解决方式有多种,我们通过了尝试对比了各种方案之后选择了其中一种较为简便的就是采用Gson的fromJson方法来解决,具体代码如下:
运行结果如下,result的值以我们期望的LeaderboardResp形式存储
四、原理分析
1. 先理解泛型与编译器虚拟机的关系以及什么是擦除?
解析: Java语言的泛型基本上是在编译器中实现的。由编译器执行类型检测和推断后生成普通的非泛型的字节,虚拟机是完全无感知泛型存在的,这种实现技术称为擦除。编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除。
2. 为什么使用Jackson的readValue方法解析JSON字符串后result的属性值会是LinkedHashMap而不是我们指定的LeaderboardResp呢?
解析:泛型只在编译期间起到检测作用,当编译器将泛型类编译完成之后,泛型类的类型参数都被全部擦除。接下来在运行期间虚拟机并不知道泛型的存在,当对JSON字符串进行解析时由于泛型被擦除了导致虚拟机并不知道要将其解析成哪种类型,所以就解析为了默认的LinkedHashMap类型,导致出现了上面的场景。
3. 那Gson是如何解决泛型擦除这种情况呢?
我们来看看这一句核心代码
解析:Gson的做法非常巧妙,如上面的代码所示,将需要获取类型的泛型类作为TypeToken的泛型参数构造一个匿名的子类,然后通过getType()方法就可以获取到我们想要的泛型类的泛型参数类型。可以理解为是将泛型类型存起来,解决了泛型擦除的问题。
五、最后
感谢您的阅读,如果喜欢本文欢迎关注和转发,本头条号将持续分享IT技术知识。对于文章内容有其他想法或意见建议等,欢迎提出共同讨论共同进步。如果您对于此场景有更好的解决方案也欢迎提出讨论。
JDk(Java Development Kit)称为Java开发包或Java开发工具,是一个编写Java的Applet小程序和应用程序的程序开发环境。
¥498.00
¥399.00
¥299.00
¥29.00