2021SC@SDUSC
本文在个人博客同步发出,地址Redbit的个人历程
概要
上一篇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>
返回。
透过代码,可以体会到开发者的思路:
- 对存放不同类型的对象数组执行反序列化,要细化对token的操作。对单一类型数组的反序列化都需要预检查token的合法性,既然需要更复杂的操作,不如像
parseObject(String, Class<T>)
一样,完全交给反序列化器操作,降低单一方法的复杂度,使用层级结构解决代码繁杂问题。 - 使用反序列化器完成操作后,返回
Object[]
类型的数组,将其转化为List<Object>
再返回。一个小小的步骤,是开发者对用户的友好。有读者可能会有疑问,为什么不直接返回一个Object[]
,而是转化之后再返回。这是因为fastjson开发者方便用户以更规范的数据结构存储反序列化的结果。Object
是所有类型的超类,这也说明除了Object
自己的数组Object[]
之外,不可能有其他类型的数组可以存放反序列化的结果。用户的程序中必然出现Object[]
,但是这样是很不规范的程序写法,而转化为List<Object>
后,用户程序中只出现了List<>
,这是一个很规范,很安全的数据结构,同时也不影响用户对数组内容的读写等操作。
从这里可以看出,fastjson开发者尽可能帮助用户解决类型转化、存储、线程安全等问题,同时也规范fastjson包内的代码,让接口对外提供的服务更符合标准。
同时,我们将本方法与之前所介绍的parseArray(String, Class<T>)
做对比,可以发现这两个API除了开始的一段代码(检查数据、使用配置初始化反序列化器等等)相同,其他代码存在较大的差异:
- 本方法调用
parser.parseArray(Type[])
方法,而单一类型的API调用的是parser.parseArray(Class<T>, List<T>)
。数据返回的方式也不同,本方法返回Object[]
类型,单一类型API通过传入的List<T>
数据结构存储对象数组,不返回(void)。 - 本方法内部不存在对token的直接操作,而单一类型API对token进行了合法性检查
分析原因,我个人认为,单一类型数组对象反序列化的token检查较简单,可以直接放在API调用的第一层内,而对规定固定类型的API内部token检查较复杂,可以单独提取作为一个方法。至于返回数据的方式、类型区别,更多的是因为parser
内部逻辑需要,对规定类型的数组直接返回Object[]
更方便。
最后
本文对parseArray(String, Type[])
API开展了第一步深入研究,可以理解内部实现逻辑,对操作顺序、架构的考量、与前文parseArray(String, Class<T>)
API的异同点,从中读出如此处理的原因与巧思,学习开发者的思路。
下次,我们将进一步深入parser.parseArray()
系列的方法,查看通用的反序列化器内部如何对每个字段匹配反序列化器实例(具体类型的反序列化器)。
感谢各位老师的阅读与指导!