7
在TypeUtils的computeGetters方法中 这里的clazz.getMethods(),不能保证子类的get方法在父类的get方法之后,就可能导致父类的get方法覆盖子类的get方法,使字段信息中获取到的字段类型为Object,导致WriteNullStringAsEmpty不能生效。
在TypeUtils的computeGetters方法中 这里的clazz.getMethods(),不能保证子类的get方法在父类的get方法之后,就可能导致父类的get方法覆盖子类的get方法,使字段信息中获取到的字段类型为Object,导致WriteNullStringAsEmpty不能生效。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.junit.Test;
public class Issue3655 {
@Test
public void test1() {
B b = new B(null);
System.out.println(JSON.toJSONString(b, SerializerFeature.WriteNullListAsEmpty));
}
public static abstract class A {
public abstract Object getData();
}
public static class B extends A {
private String data;
public B(String data) {
this.data = data;
}
public String getData() {
return this.data;
}
public void setData(String data) {
this.data = data;
}
}
}
1.2.75 存在此问题
使用 SerializerFeature.WriteNullStringAsEmpty
@wenshao 这个问题关闭掉,是不解决吗?
我之前发的TestCase确实是错误的,写成WriteNullListsAsEmpty
了.
但是问题还是存在
package com.alibaba.json.bvt.issue_3600;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.junit.Assert;
import org.junit.Test;
public class Issue3655 {
@Test
public void test1() {
issue3655_b b = new issue3655_b(null, null, null, null, null, null, null, null, null);
String left = JSON.toJSONString(b, SerializerFeature.WriteNullStringAsEmpty);
System.out.println(left);
Assert.assertEquals(
"{\"data\":\"\",\"data2\":\"\",\"data3\":\"\",\"data4\":\"\",\"data5\":\"\",\"data6\":\"\",\"data7\":\"\",\"data8\":\"\",\"data9\":\"\"}", left);
}
@Test
public void test2() {
issue3655_c c = new issue3655_c(null, null, null, null, null, null, null, null, null);
String left = JSON.toJSONString(c, SerializerFeature.WriteNullStringAsEmpty);
System.out.println(left);
Assert.assertEquals(
"{\"data\":\"\",\"data2\":\"\",\"data3\":\"\",\"data4\":\"\",\"data5\":\"\",\"data6\":\"\",\"data7\":\"\",\"data8\":\"\",\"data9\":\"\"}", left);
}
public static class issue3655_b extends issue3655_a {
private String data;
private String data2;
private String data3;
private String data4;
private String data5;
private String data6;
private String data7;
private String data8;
private String data9;
public String getData() {return data;}
public String getData2() {return data2;}
public String getData3() {return data3;}
public String getData4() {return data4;}
public String getData5() {return data5;}
public String getData6() {return data6;}
public String getData7() {return data7;}
public String getData8() {return data8;}
public String getData9() {return data9;}
public void setData(String data) {this.data = data;}
public void setData2(String data) {this.data2 = data2;}
public void setData3(String data) {this.data3 = data3;}
public void setData4(String data) {this.data4 = data4;}
public void setData5(String data) {this.data5 = data5;}
public void setData6(String data) {this.data6 = data6;}
public void setData7(String data) {this.data7 = data7;}
public void setData8(String data) {this.data8 = data8;}
public void setData9(String data) {this.data9 = data9;}
public issue3655_b(
String data, String data2, String data3, String data4, String data5,
String data6, String data7, String data8, String data9) {
this.data = data;
this.data2 = data2;
this.data3 = data3;
this.data4 = data4;
this.data5 = data5;
this.data6 = data6;
this.data7 = data7;
this.data8 = data8;
this.data9 = data9;
}
}
@Getter
@Setter
@AllArgsConstructor
public static class issue3655_c extends issue3655_a {
private String data;
private String data2;
private String data3;
private String data4;
private String data5;
private String data6;
private String data7;
private String data8;
private String data9;
}
public static abstract class issue3655_a {
public abstract Object getData();
public abstract Object getData2();
public abstract Object getData3();
public abstract Object getData4();
public abstract Object getData5();
public abstract Object getData6();
public abstract Object getData7();
public abstract Object getData8();
public abstract Object getData9();
}
}
重复几次testcase可以发现,基本上每次的输出都不同,并且testcase大概率不通过.
比如输出:
org.junit.ComparisonFailure:
预期:{"data":"","data2":"","data3":"","data4":"","data5":"","data6":"","data7":"","data8":"","data9":""}
实际:{"data":"","data3":"","data4":"","data5":""}
问题就出在那个clazz.getMethods()
,getMethods()不保证顺序-
在一般实现里就是地址顺序.
因为Object
自带10+方法,所以只有一个字段的对象,带上字段的getter,setter也就十几个方法,子类的get方法在父类的get方法之后概率还挺高,一旦字段多起来概率就下去了.
@wenshao