Android架构实战(四)—— Gson

Android架构实战(三)—— Retrofit中,我们讲到了Retrofit默认是用Gson作解析。但这并意味着我们就能够一帆风顺的使用了,因为在实践过程中,变通的地方很多,默认的解析方法往往会遇到许多困难,这里还是决定单独拿出来讲一下。

其实GSON并不能算是一种框架级别的工具,不过它却对快速开发能够起到极大的促进作用。GSON是由谷歌开发的JSON快速解析类,官方文档:Gson User Guide(需要翻墙),项目Github地址:google/gson。Gson采用了序列化的方式解析JSON串(因此,支持了Gson解析的类在序列化方面都会有很高的兼用性),在赋值的时候直接操纵内存,在速度上和简洁性上,都会比android基本的解析方法好很多。因此,大部分的android开发人员和开源框架都使用了GSON。

一、基础使用

在导入Gson的jar包后,就可以按如下命令开始使用Gson了:
<span style="font-size:14px;">Gson gson = new Gson(); // 可以构造单例进行处理
String jsonString = gson.toJson(myClass);
MyClass myClass = gson.fromJson(jsonString, MyClass.class);</span>
其中,需要对MyClass中的变量使用注解进行标注。Gson主要提供了以下几种注解:
  • @Expose:被该注解标注的变量会被GSON处理(默认所有变量都会处理)。如果在一个类中,只存在个别变量需要被GSON解析,则可以使用Expose作单独标注。相反的,如果只有个别变量不需要被GSON解析,则可以对需要忽略的变量使用transient关键词(不是注解),而其他变量也不需要再额外添加Expose注解了。
  • @SerializedName("keyName"):标识JsonObject中对应的Key值。默认情况下,Gson会将变量名当做Key值来处理。但是通常情况下,正式的android包会做混淆处理,导致变量名被改变,因此,必须对每一个变量都使用SerializedName做标注才能保证不会出错。
在GSON中,JsonObject对应为一个Class,JsonArray对应为一个List,因此,在遇到嵌套的情况下,按照这个关系进行对应的处理即可。
值得一提的是,GSON对集合类型(List,  Set)的处理存在一定的限制,即在反序列化的过程中,没有办法去识别集合中的泛型类到底是什么,因此,在反序列化的时候,需要用户手动指定类型:
<span style="font-size:14px;">Type collectionType = new TypeToken<List<MyClass>>(){}.getType();
List<MyClass> classList = gson.fromJson(json, collectionType);</span>
在Retrofit的中,默认GsonConverter已经集成了这个过程了,因此在使用Retrofit的时候可以不用有这个顾虑

二、拓展问题解决方法

正如我一直提到的,高度封装的简洁性必然会带来一定的拓展性问题,许多时候,默认的Gson解析方法可能无法支持开发人员的一些需求。我主要遇到过的一些情况有
  1. 服务器返回不标准的JSON串,如"{"key":"{"chilekey":"childvalue}"}"。在这个例子中,key对应的value应当是一个JsonObject,但由于value外边包裹了一个引号,Gson会识别为String。这个时候如果尝试将其直接转化为一个自定义Class,则会报错。为了解决这个问题,只能拿一个String去存储值,在需要用到的时候通过getter对其进行一个转化, 示例如下:
    <span style="font-size:14px;">class MyClass {
        @SerializedName("key")
        String childString;
    
        transient ChildClass childClass;
    
        public ChildClass getChildClass() {
            if (childClass == null) // 只进行一次转化,提高效率
                childClass = (new Gson()).fromJson(childString, ChildClass.class);
            return childClass;
        }
    
        class ChildClass {
            @SerializedName("childkey")
            String value;
        }
    }</span>

  2. 返回类型不固定。为了提高复用性,服务器在很多时候会在同一个接口返回不同类型的值,这就需要我们动态的去设置Gson的解析类。然而,由于Gson是通过静态的注解方法进行设置的,因此没有办法对返回结果做动态判断。想要实现这个效果,要么就通过请求值去判断返回类型,然后对每一个返回类型写一个接口,要么就得用一个共通的类去存储中间变量。第一种方法,相对来说比较啰嗦,复用性较低。因此,比较推荐使用第二种方法。那么,应当拿什么变量来做这个中间值呢?答案是LinkedTreeMap。当Gson不知道应当按照什么类去解析的时候,就会将所有的变量转化一个LiknedTreeMap。LinkedTreeMap本质上是一个Map,通过这个Map,就可以动态的去获取当中所包含的key和value了。
可以看到,LinkedTreeMap是Gson中一个解决拓展性的问题关键类,当遇到任何不兼容或者非静态的问题时,都可以临时摒弃GSON的封装方法,自己来进行有针对性的解析,这个开发思路显得相当的优雅。当然,LinkedTreeMap会将所有的变量都进行读出和转换,效率上或许会受到一定的影响,因此不适宜过多使用。

三、小结

解决了拓展性的问题后,对于Gson的使用就基本一帆风顺了。在使用的时候具体问题具体分析即可。

RxJava、Retrofit和Gson这三个库的结合,在构造代码框架的时候起到了决定性的作用,这三个库之间相辅相成,相互配合,从各个方面都对代码的整体质量有一个提升(解耦、复用、简洁、高性能)。因此,十分推荐各位开发人员的时候可以已这个三个库为基础进行架构的搭建。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值