1. 现象
我有一个类,其中有一个getInfo方法
@EqualsAndHashCode(callSuper = true)
@Data
public class Student extends AbstractUser{
private String school;
private String clazz;
public String getInfo() {
return toString();
}
}
1.2
然后我将这个类的对象进行序列号后输出:
@Test
public void toJsonStringTest() {
Student student = new Student();
student.setSchool("");
student.setClazz("");
student.setName("");
student.setAge(0);
System.out.println(JSON.toJSONString(student));
}
1.3
发现最终输出的结果与预期不符:有一个info 的属性,fastjson在序列号的时候,将getInfo视作类的一个属性的get方法了
{"age":0,"clazz":"","info":"Student(school=, clazz=)","name":"","school":""}
2. 分析原因
2.1 JSON.java
首先,我们进入到toJSONString 的方法中,
public static String toJSONString(Object object, //
SerializeConfig config, //
SerializeFilter[] filters, //
String dateFormat, //
int defaultFeatures, //
SerializerFeature... features) {
SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
try {
JSONSerializer serializer = new JSONSerializer(out, config);
if (dateFormat != null && dateFormat.length() != 0) {
serializer.setDateFormat(dateFormat);
serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
}
if (filters != null) {
for (SerializeFilter filter : filters) {
serializer.addFilter(filter);
}
}
//可以发现最核心的代码在这里,这里是实际上做序列化的地方
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
2.2 JSONSerializer
在JSONSerializer中,会新建一个writer(ASM)进行序列号
public final void write(Object object) {
if (object == null) {
out.writeNull();
return;
}
Class<?> clazz = object.getClass();
//创建一个ASM的序列化writer
ObjectSerializer writer = getObjectWriter(clazz);
try {
writer.write(this, object, null, null, 0);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
}
}
2.3 SerializeConfig
private ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {
ObjectSerializer writer = serializers.get(clazz);
//加载AutowiredObjectSerializer,自定义序列号器
if (writer == null) {
}
//使用JSON 的类加载器再加载一下(如果不一样)
if (writer == null) {
}
if (writer == null) {
String className = clazz.getName();
Class<?> superClass;
//一些已经实现好的类,例如Map、枚举、一些异常类 这些特殊类;
else {
//java bean需要创建一个ASM 的writer
if (create) {
writer = createJavaBeanSerializer(clazz);
put(clazz, writer);
}
}
if (writer == null) {
writer = serializers.get(clazz);
}
}
return writer;
}
public final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
//首先获取到bean的信息,属性等字段;info数据也是在这里获取到的
SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
return MiscCodec.instance;
}
// 创建javaBean序列化器
return createJavaBeanSerializer(beanInfo);
}
2.4 TypeUtils
通过反射获取到类的具体信息,并组装成BeanInfo
public static SerializeBeanInfo buildBeanInfo(Class<?> beanType //
, Map<String,String> aliasMap //
, PropertyNamingStrategy propertyNamingStrategy //
, boolean fieldBased //
){
JSONType jsonType = TypeUtils.getAnnotation(beanType,JSONType.class);
String[] orders = null;
final int features;
String typeName = null, typeKey = null;
if(jsonType != null){
orders = jsonType.orders();
typeName = jsonType.typeName();
if(typeName.length() == 0){
typeName = null;
}
PropertyNamingStrategy jsonTypeNaming = jsonType.naming();
if (jsonTypeNaming != null && jsonTypeNaming != PropertyNamingStrategy.CamelCase) {
propertyNamingStrategy = jsonTypeNaming;
}
features = SerializerFeature.of(jsonType.serialzeFeatures());
for(Class<?> supperClass = beanType.getSuperclass()
; supperClass != null && supperClass != Object.class
; supperClass = supperClass.getSuperclass()){
JSONType superJsonType = TypeUtils.getAnnotation(supperClass,JSONType.class);
if(superJsonType == null){
break;
}
typeKey = superJsonType.typeKey();
if(typeKey.length() != 0){
break;
}
}
for(Class<?> interfaceClass : beanType.getInterfaces()){
JSONType superJsonType = TypeUtils.getAnnotation(interfaceClass,JSONType.class);
if(superJsonType != null){
typeKey = superJsonType.typeKey();
if(typeKey.length() != 0){
break;
}
}
}
if(typeKey != null && typeKey.length() == 0){
typeKey = null;
}
} else{
features = 0;
}
// fieldName,field ,先生成fieldName的快照,减少之后的findField的轮询
Map<String,Field> fieldCacheMap = new HashMap<String,Field>();
// 在这里获取到定义好的属性
ParserConfig.parserAllFieldToCache(beanType, fieldCacheMap);
//这里将一些方法也作为属性封装
List<FieldInfo> fieldInfoList = fieldBased
? computeGettersWithFieldBase(beanType, aliasMap, false, propertyNamingStrategy) //
: computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, false, propertyNamingStrategy);
FieldInfo[] fields = new FieldInfo[fieldInfoList.size()];
fieldInfoList.toArray(fields);
FieldInfo[] sortedFields;
List<FieldInfo> sortedFieldList;
if(orders != null && orders.length != 0){
sortedFieldList = fieldBased
? computeGettersWithFieldBase(beanType, aliasMap, true, propertyNamingStrategy) //
: computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, true, propertyNamingStrategy);
} else{
sortedFieldList = new ArrayList<FieldInfo>(fieldInfoList);
Collections.sort(sortedFieldList);
}
sortedFields = new FieldInfo[sortedFieldList.size()];
sortedFieldList.toArray(sortedFields);
if(Arrays.equals(sortedFields, fields)){
sortedFields = fields;
}
return new SerializeBeanInfo(beanType, jsonType, typeName, typeKey, features, fields, sortedFields);
}
public static List<FieldInfo> computeGetters(Class<?> clazz, //
JSONType jsonType, //
Map<String,String> aliasMap, //
Map<String,Field> fieldCacheMap, //
boolean sorted, //
PropertyNamingStrategy propertyNamingStrategy //
){
Map<String,FieldInfo> fieldInfoMap = new LinkedHashMap<String,FieldInfo>();
boolean kotlin = TypeUtils.isKotlin(clazz);
// for kotlin
Constructor[] constructors = null;
Annotation[][] paramAnnotationArrays = null;
String[] paramNames = null;
short[] paramNameMapping = null;
Method[] methods = clazz.getMethods();
// 遍历方法
for(Method method : methods){
String methodName = method.getName();
int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
String label = null;
//将void 或者 其他不满足条件的方法给过滤了
//将get方法get后面的作为数值
if(methodName.startsWith("get")){
fieldInfoMap.put(propertyName, fieldInfo);
}
}
Field[] fields = clazz.getFields();
computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);
return getFieldInfos(clazz, sorted, fieldInfoMap);
}
3. 结果
最终在fastJson生成的ASM序列号器中就会有一个由getInfo方法得到的info属性,最终序列化的时候会将info数据也给打印出来