1. 程式人生 > >fastjson反序列化失敗autoType is not support

fastjson反序列化失敗autoType is not support

描述

通過fastjson反序列化某javabean時失敗,並丟擲以下異常:

Could not deserialize: autoType is not support. com.xxx.Shop; nested exception is com.alibaba.fastjson.JSONException: autoType is not support. com.xxx.Shop
	at com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer.deserialize(GenericFastJsonRedisSerializer.java:37)

然而只有專案第一次反序列化該javabean時會拋異常失敗,復現方式只有重啟專案後的第一次反序列化操作。

過程

查詢官方文件,開啟AutoType的方法
enable_autotype

但是文件中的方法均測試無效,無奈debug原始碼,發現丟擲異常的程式碼為
com.alibaba.fastjson.parser.ParserConfig的1125行程式碼:

JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, clazz, propertyNamingStrategy);
if (beanInfo.creatorConstructor !=
null && autoTypeSupport) { throw new JSONException("autoType is not support. " + typeName); }

經與正常反序列化的javabean比較後,發現反序列化失敗的javabean在如上程式碼執行時,beanInfo.creatorConstructor的值不為null,最後丟擲autoType is not support的異常。

繼續追蹤,在com.alibaba.fastjson.util.JavaBeanInfo283行程式碼判斷反序列化失敗的javabean為介面或抽象類:

boolean isInterfaceOrAbstract = clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers());

再於com.alibaba.fastjson.util.JavaBeanInfo381行程式碼的if判斷分支下給beanInfo.creatorConstructor賦值:

else if (!isInterfaceOrAbstract){
    ...
    for (Constructor constructor : constructors) {
        Class<?>[] parameterTypes = constructor.getParameterTypes();
    
        if (className.equals("org.springframework.security.web.authentication.WebAuthenticationDetails")) {
            if (parameterTypes.length == 2 && parameterTypes[0] == String.class && parameterTypes[1] == String.class) {
                creatorConstructor = constructor;
                creatorConstructor.setAccessible(true);
                paramNames = ASMUtils.lookupParameterNames(constructor);
                break;
            }
        }
    
        if (className.equals("org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken")) {
            if (parameterTypes.length == 3
                    && parameterTypes[0] == Object.class
                    && parameterTypes[1] == Object.class
                    && parameterTypes[2] == Collection.class) {
                creatorConstructor = constructor;
                creatorConstructor.setAccessible(true);
                paramNames = new String[] {"principal", "credentials", "authorities"};
                break;
            }
        }
    
        if (className.equals("org.springframework.security.core.authority.SimpleGrantedAuthority")) {
            if (parameterTypes.length == 1
                    && parameterTypes[0] == String.class) {
                creatorConstructor = constructor;
                paramNames = new String[] {"authority"};
                break;
            }
        }
    
        boolean is_public = (constructor.getModifiers() & Modifier.PUBLIC) != 0;
        if (!is_public) {
            continue;
        }
        String[] lookupParameterNames = ASMUtils.lookupParameterNames(constructor);
        if (lookupParameterNames == null || lookupParameterNames.length == 0) {
            continue;
        }
    
        if (creatorConstructor != null
                && paramNames != null && lookupParameterNames.length <= paramNames.length) {
            continue;
        }
    
        paramNames = lookupParameterNames;
        // 有引數構造方法給beanInfo.creatorConstructor賦值
        creatorConstructor = constructor;
    }
}

最終定位專案中通過fastjson反序列化失敗,是因為該javabean沒有無參構造方法,被fastjson判斷為介面或抽象類,最終丟擲autoType is not support的異常。

解決

給javabean新增無參構造方法。