https://github.com/alibaba/fastjson/issues/3693
上面的 #3639 提出了一个bug,即通过@JSONField#deserializeUsing
属性指定的自定义反序列化器被后续的代码覆盖,并在1.2.76中进行了修复,然而我们在使用升级后的1.2.76时发现1.2.75中没有问题的代码出现报错,经定位是该Issue的解决方案引入了新的Bug。
我们的代码是构造了一个ClassA<ClassB<String>>
这种样式的类,ClassA<T>
的声明中有一个字段T data
,实际类型是ClassB<String>
,现在1.2.76的修复方案,虽然确保了@JSONField#deserializeUsing
属性指定的自定义反序列化器具有最高的优先级,但是在我们的场景下,并没有使用@JSONField
注解,原本ClassA
中T data
字段的反序列化器应该是针对运行时实际类型ClassB<String>
创建的,现在却获取到的是一个普通的Object
的通用反序列化器。
具体代码如下,1.2.76中:
public ObjectDeserializer getFieldValueDeserilizer(ParserConfig config) {
if (fieldValueDeserilizer == null) {
JSONField annotation = fieldInfo.getAnnotation();
if (annotation != null && annotation.deserializeUsing() != Void.class) {
Class<?> deserializeUsing = annotation.deserializeUsing();
try {
fieldValueDeserilizer = (ObjectDeserializer) deserializeUsing.newInstance();
} catch (Exception ex) {
throw new JSONException("create deserializeUsing ObjectDeserializer error", ex);
}
} else {
fieldValueDeserilizer = config.getDeserializer(fieldInfo.fieldClass, fieldInfo.fieldType);
}
}
return fieldValueDeserilizer; // 这个成员变量和返回值不为空
}
这个方法无论成员变量fieldValueDeserilizer
初始的状态是否为null
,该方法执行后,成员变量fieldValueDeserilizer
都会被转为非null
的值,考虑了通过@JSONField
注解自定义反序列化器的场景。
但是在下面的方法中:
@Override
public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
if (this.fieldValueDeserilizer == null) {
getFieldValueDeserilizer(parser.getConfig());
}
ObjectDeserializer fieldValueDeserilizer = this.fieldValueDeserilizer;
Type fieldType = fieldInfo.fieldType;
if (objectType instanceof ParameterizedType) {
ParseContext objContext = parser.getContext();
if (objContext != null) {
objContext.type = objectType;
}
if (fieldType != objectType) {
fieldType = FieldInfo.getFieldType(this.clazz, objectType, fieldType);
if (fieldValueDeserilizer == null) { // 该处修改导致下面一行失效
fieldValueDeserilizer = parser.getConfig().getDeserializer(fieldType); // 代码失效,原有逻辑无法正确执行
}
}
}
1.2.76中的67行进行了一个null
判断,但是ObjectDeserializer fieldValueDeserilizer = this.fieldValueDeserilizer
即局部变量fieldValueDeserilizer
正是成员变量this.fieldValueDeserilizer
,而后者如上面所说的,在该方法调用上面的getFieldValueDeserilizer
之后永远不会为null
,所以导致68行代码不会被执行,而之前的版本能够处理这种嵌套的场景,原因就在于68行获取了一个与实际运行时类型匹配的反序列化器,现在这样的修复方案使得68行代码失效了,从而嵌套泛型的场景下失效,将给现有生产代码造成巨大影响