Java序列化与反序列化Json通常会使用Gson和Jackson这两个框架,之前因为公司都是用的Gson也没太在意。最近碰到了一个这两框架在反序列化上有些不太一样的地方。
通常在Java中我们反序列化一个Json字符串是,如果我们不想定义一个具体的类,我们会把它反序列化为Java中的Map类,这时候我们其实没有提供任何Map中的value的类型的信息,序列化框架需要自己根据json字符串来判断应该反序列化为哪个类。这里我发现Gson在处理数字的反序列化,会默认都反序列化成Double,而Jackson则可以智能的判断。
为什么会产生这样的差异?查阅源码以后我发现,这两个框架在对JsonToken的定义上就存在差异。
|
|
|
|
可以看到,Jackson在JsonToken中就将数字定义成两种类型VALUE_NUMBER_INT和VALUE_NUMBER_FLOAT,而Gson中只有一种NUMBER。
事实上这两个框架在解析数字时都区分了整型和浮点型,代码可以参见
Gson中JsonReader的peekNumber()方法
Jackson中ReaderBasedJsonParser的_parsePosNumber()方法
但是Gson在将其转成JsonToken时将PEEKED_LONG和PEEKED_NUMBER统一返回成了JsonToken.NUMBER
可以参见JsonReader中的peek()函数
|
|
而上层在反序列化时是以JsonToken为类型的参考依据的(当用户没有提供类型信息时),比如我们可以看ObjectTypeAdapter(通常我们不给类型,gson就会按Object类型来反序列化)中的反序列化
|
|
综上所述,gson其实是可以做到识别整型和浮点型,但是在上层隐藏了这个信息,不知道是出于什么考虑。