fastjson源码解析——反序列化(六)

2021SC@SDUSC

本文在CSDN个人博客同步发出,地址CSDN博客

概要

上一篇fastjson源码解析——反序列化(五)介绍了fastjson中,parseArray(String, Class<T>)API的结构,从中了解fastjson对单一类型JSON对象数组的处理顺序、逻辑等,并与parseObject(String, Class<T>)的执行逻辑做对比,透过JSON对象数组的结构看到fastjson设计的巧妙之处。本文将从fastjson对象数组反序列化的另外一个API,对存放不同类型对象的JSON数组反序列化的parseArray(String, Type[])开始,探究fastjson对此类数组的反序列化执行逻辑。
本文将更着重于两个APIparseArray(String, Class<T>)parseArray(String, Type[])的对比,从对比中分析两者的差异

1. parseArray(String, Type[])方法

这是规定每个元素类型的数组反序列化所需调用的第一个API,也是fastjson中最为广泛使用的一个API。
先看代码:

    public static List<Object> parseArray(String text, Type[] types) {
        return parseArray(text, types, ParserConfig.global);
    }

parseArray(String, Type[])方法的逻辑与parseArray(String, Class<T>)并没有区别,都是深入调用了带有配置ParserConfig.global的API,都是为了让用户能够按照自己的需求,调用不同的API。初次使用者,或是不需要复杂配置的用户,可以调用最简单的APIparseArray(String, Type[]);需要深度定制反序列化操作的使用者,可以通过调用带配置的API实现自己的定制,同时满足不同人群对反序列化的需要,而代码也不再冗余。
其他部分与前文描述的parseArray(String, Class<T>)并无明显区别,可参考前文
接下来看带配置的APIparseArray(String, Type[], ParserConfig)

2. parseArray(String, Type[], ParserConfig)方法

本方法对规定对应元素类型的JSON对象数组的反序列化执行逻辑、架构、顺序等,是这类方法的一个重点。
代码:

    public static List<Object> parseArray(String text, Type[] types, ParserConfig config) {
        if (text == null) {//若传入数据为空,直接返回null
            return null;
        }

        List<Object> list;
        /** 使用config创建默认通用JSON反序列化器,
        * 后续将数据交给反序列化器完成对每个字段的反序列化
        */
        DefaultJSONParser parser = new DefaultJSONParser(text, config);
        Object[] objectArray = parser.parseArray(types);//与单一类型API的最大区别,直接使用类型执行反序列化操作
        if (objectArray == null) {
            list = null;
        } else {
            list = Arrays.asList(objectArray);//转化为List<Object>
        }

        parser.handleResovleTask(list);

        parser.close();//释放反序列化器

        return list;
    }

parseArray(String, Type[], ParserConfig)这个方法,先初始化反序列化器,接着使用反序列化器执行反序列化,最后转化为所需类型的List<Object>返回。
透过代码,可以体会到开发者的思路:

  1. 对存放不同类型的对象数组执行反序列化,要细化对token的操作。对单一类型数组的反序列化都需要预检查token的合法性,既然需要更复杂的操作,不如像parseObject(String, Class<T>)一样,完全交给反序列化器操作,降低单一方法的复杂度,使用层级结构解决代码繁杂问题。
  2. 使用反序列化器完成操作后,返回Object[]类型的数组,将其转化为List<Object>再返回。一个小小的步骤,是开发者对用户的友好。有读者可能会有疑问,为什么不直接返回一个Object[],而是转化之后再返回。这是因为fastjson开发者方便用户以更规范的数据结构存储反序列化的结果。Object是所有类型的超类,这也说明除了Object自己的数组Object[]之外,不可能有其他类型的数组可以存放反序列化的结果。用户的程序中必然出现Object[],但是这样是很不规范的程序写法,而转化为List<Object>后,用户程序中只出现了List<>,这是一个很规范,很安全的数据结构,同时也不影响用户对数组内容的读写等操作。

    从这里可以看出,fastjson开发者尽可能帮助用户解决类型转化、存储、线程安全等问题,同时也规范fastjson包内的代码,让接口对外提供的服务更符合标准。

同时,我们将本方法与之前所介绍的parseArray(String, Class<T>)做对比,可以发现这两个API除了开始的一段代码(检查数据、使用配置初始化反序列化器等等)相同,其他代码存在较大的差异:

  1. 本方法调用parser.parseArray(Type[])方法,而单一类型的API调用的是parser.parseArray(Class<T>, List<T>)。数据返回的方式也不同,本方法返回Object[]类型,单一类型API通过传入的List<T>数据结构存储对象数组,不返回(void)。
  2. 本方法内部不存在对token的直接操作,而单一类型API对token进行了合法性检查

分析原因,我个人认为,单一类型数组对象反序列化的token检查较简单,可以直接放在API调用的第一层内,而对规定固定类型的API内部token检查较复杂,可以单独提取作为一个方法。至于返回数据的方式、类型区别,更多的是因为parser内部逻辑需要,对规定类型的数组直接返回Object[]更方便。

最后

本文对parseArray(String, Type[])API开展了第一步深入研究,可以理解内部实现逻辑,对操作顺序、架构的考量、与前文parseArray(String, Class<T>)API的异同点,从中读出如此处理的原因与巧思,学习开发者的思路。
下次,我们将进一步深入parser.parseArray()系列的方法,查看通用的反序列化器内部如何对每个字段匹配反序列化器实例(具体类型的反序列化器)。
感谢各位老师的阅读与指导!

发表评论