版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433443
最近在使用fastjson做Java bean的序列化和反序列化时遇到一个小问题:
public class A<T>{
private T value;
public A setValue(T value){
this.value = value;
return this;
}
public T getValue(){
return value;
}
}
public class B extends A<Integer>{
@Override
public A setValue(Integer value){
this.value = value;
// do something
return this;
}
}
如上是A是泛型父类,对value字段有setter/getter方法,B为A的子类,重写了setValue方法。从上面的setValue的返回值不是void
可知这个写法不是标准java bean的setter方法(标准java bean要求setter方法返回为void)。fastjson是支持这种非标准的setter方法的。
实际测试过程中A的实例可以正确序列化和返回序列化,但B的实例在反序列化过程中没有对value字段进行解析,也就是说把value字段给丢了!
通过跟踪fastjson的源码,找到了原因,问题出在JavaBeanInfo com.alibaba.fastjson.util.JavaBeanInfo.build(Class<?> clazz, Type type, PropertyNamingStrategy propertyNamingStrategy, boolean fieldBased, boolean compatibleWithJavaBean)
方法上
,参见源码 JavaBeanInfo.java line 648
以下是该方法的代码片段:
for (Method method : methods) { //
int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
String methodName = method.getName();
if (Modifier.isStatic(method.getModifiers())) {
continue;
}
// support builder set
Class<?> returnType = method.getReturnType();
// 判断返回值类型是否为void或为DeclaringClass
if (!(returnType.equals(Void.TYPE) || returnType.equals(method.getDeclaringClass()))) {
continue;
}
//....................
}
上面代码中最后一段逻辑判断,返回值类型是否为void
或为DeclaringClass,如果都不是就放弃该方法。
在本例中A,B中的setValue方法返回类型为A,所以肯定不满足void,而这两个方法的DeclaringClass都为B,所以也不满足第二个条件。所以对于B而言父类中的setValue方法以及自己类中重写的setValue方法因为返回类型问题在这里都被fastjson判断为非setter方法给跳过了,所以后续的反序列化过程中自然就没有value字段。
怎么解决呢?
把B类中的setValue返回类型改为B就可以了。本来在这里返回类型为A就不太对,是我之前写错了。。
public class B extends A<Integer>{
@Override
public B setValue(Integer value){
this.value = value;
// do something
return this;
}
}