2

fastjson反序列化失败autoType is not support

 1 year ago
source link: https://wakzz.cn/2019/01/03/java/fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%A4%B1%E8%B4%A5autoType%20is%20not%20support/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

fastjson反序列化失败autoType is not support

祈雨的博客
2019-01-03

通过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添加无参构造方法。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK