in fastjson1-compatible/src/main/java/com/alibaba/fastjson/util/TypeUtils.java [679:1024]
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<>();
boolean kotlin = TypeUtils.isKotlin(clazz);
// for kotlin
Constructor[] constructors = null;
Annotation[][] paramAnnotationArrays = null;
String[] paramNames = null;
short[] paramNameMapping = null;
Method[] methods = clazz.getMethods();
try {
Arrays.sort(methods, new MethodInheritanceComparator());
} catch (Throwable ignored) {
// ignored
}
for (Method method : methods) {
String methodName = method.getName();
int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
String label = null;
if (Modifier.isStatic(method.getModifiers())) {
continue;
}
Class<?> returnType = method.getReturnType();
if (returnType.equals(Void.TYPE)) {
continue;
}
if (method.getParameterTypes().length != 0) {
continue;
}
if (returnType == ClassLoader.class
|| returnType == InputStream.class
|| returnType == Reader.class) {
continue;
}
if ("getMetaClass".equals(methodName)
&& "groovy.lang.MetaClass".equals(returnType.getName())) {
continue;
}
if ("getSuppressed".equals(methodName)
&& method.getDeclaringClass() == Throwable.class) {
continue;
}
if (kotlin && isKotlinIgnore(clazz, methodName)) {
continue;
}
/*
* 如果在属性或者方法上存在JSONField注解,并且定制了name属性,不以类上的propertyNamingStrategy设置为准,以此字段的JSONField的name定制为准。
*/
boolean fieldAnnotationAndNameExists = false;
JSONField annotation = TypeUtils.getAnnotation(method, JSONField.class);
if (annotation == null) {
annotation = getSuperMethodAnnotation(clazz, method);
}
if (annotation == null && kotlin) {
if (constructors == null) {
constructors = clazz.getDeclaredConstructors();
Constructor creatorConstructor = TypeUtils.getKotlinConstructor(constructors);
if (creatorConstructor != null) {
paramAnnotationArrays = TypeUtils.getParameterAnnotations(creatorConstructor);
paramNames = TypeUtils.getKoltinConstructorParameters(clazz);
if (paramNames != null) {
String[] paramNames_sorted = new String[paramNames.length];
System.arraycopy(paramNames, 0, paramNames_sorted, 0, paramNames.length);
Arrays.sort(paramNames_sorted);
paramNameMapping = new short[paramNames.length];
for (short p = 0; p < paramNames.length; p++) {
int index = Arrays.binarySearch(paramNames_sorted, paramNames[p]);
paramNameMapping[index] = p;
}
paramNames = paramNames_sorted;
}
}
}
if (paramNames != null && paramNameMapping != null && methodName.startsWith("get")) {
String propertyName = decapitalize(methodName.substring(3));
int p = Arrays.binarySearch(paramNames, propertyName);
if (p < 0) {
for (int i = 0; i < paramNames.length; i++) {
if (propertyName.equalsIgnoreCase(paramNames[i])) {
p = i;
break;
}
}
}
if (p >= 0) {
short index = paramNameMapping[p];
Annotation[] paramAnnotations = paramAnnotationArrays[index];
if (paramAnnotations != null) {
for (Annotation paramAnnotation : paramAnnotations) {
if (paramAnnotation instanceof JSONField) {
annotation = (JSONField) paramAnnotation;
break;
}
}
}
if (annotation == null) {
Field field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
if (field != null) {
annotation = TypeUtils.getAnnotation(field, JSONField.class);
}
}
}
}
}
if (annotation != null) {
if (!annotation.serialize()) {
continue;
}
ordinal = annotation.ordinal();
serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures());
parserFeatures = Feature.of(annotation.parseFeatures());
if (annotation.name().length() != 0) {
String propertyName = annotation.name();
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
FieldInfo fieldInfo = new FieldInfo(propertyName, method, null, clazz, null, ordinal,
serialzeFeatures, parserFeatures, annotation, null, label);
fieldInfoMap.put(propertyName, fieldInfo);
continue;
}
if (annotation.label().length() != 0) {
label = annotation.label();
}
}
if (methodName.startsWith("get")) {
if (methodName.length() < 4) {
continue;
}
if ("getClass".equals(methodName)) {
continue;
}
if ("getDeclaringClass".equals(methodName) && clazz.isEnum()) {
continue;
}
char c3 = methodName.charAt(3);
String propertyName;
Field field = null;
if (Character.isUpperCase(c3) //
|| c3 > 512 // for unicode method name
) {
if (compatibleWithJavaBean) {
propertyName = decapitalize(methodName.substring(3));
} else {
propertyName = TypeUtils.getPropertyNameByMethodName(methodName);
}
propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 3);
} else if (c3 == '_') {
propertyName = methodName.substring(3);
field = fieldCacheMap.get(propertyName);
if (field == null) {
String temp = propertyName;
propertyName = methodName.substring(4);
field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
if (field == null) {
propertyName = temp; //减少修改代码带来的影响
}
}
} else if (c3 == 'f') {
propertyName = methodName.substring(3);
} else if (methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))) {
propertyName = decapitalize(methodName.substring(3));
} else {
propertyName = methodName.substring(3);
field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
if (field == null) {
continue;
}
}
boolean ignore = isJSONTypeIgnore(clazz, propertyName);
if (ignore) {
continue;
}
if (field == null) {
// 假如bean的field很多的情况一下,轮询时将大大降低效率
field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
}
if (field == null && propertyName.length() > 1) {
char ch = propertyName.charAt(1);
if (ch >= 'A' && ch <= 'Z') {
String javaBeanCompatiblePropertyName = decapitalize(methodName.substring(3));
field = ParserConfig.getFieldFromCache(javaBeanCompatiblePropertyName, fieldCacheMap);
}
}
JSONField fieldAnnotation = null;
if (field != null) {
fieldAnnotation = TypeUtils.getAnnotation(field, JSONField.class);
if (fieldAnnotation != null) {
if (!fieldAnnotation.serialize()) {
continue;
}
ordinal = fieldAnnotation.ordinal();
serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
if (fieldAnnotation.name().length() != 0) {
fieldAnnotationAndNameExists = true;
propertyName = fieldAnnotation.name();
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
}
if (fieldAnnotation.label().length() != 0) {
label = fieldAnnotation.label();
}
}
}
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
if (propertyNamingStrategy != null && !fieldAnnotationAndNameExists) {
propertyName = propertyNamingStrategy.translate(propertyName);
}
FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
annotation, fieldAnnotation, label);
fieldInfoMap.put(propertyName, fieldInfo);
}
if (methodName.startsWith("is")) {
if (methodName.length() < 3) {
continue;
}
if (returnType != Boolean.TYPE
&& returnType != Boolean.class) {
continue;
}
char c2 = methodName.charAt(2);
String propertyName;
Field field = null;
if (Character.isUpperCase(c2)) {
if (compatibleWithJavaBean) {
propertyName = decapitalize(methodName.substring(2));
} else {
propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
}
propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 2);
} else if (c2 == '_') {
propertyName = methodName.substring(3);
field = fieldCacheMap.get(propertyName);
if (field == null) {
String temp = propertyName;
propertyName = methodName.substring(2);
field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
if (field == null) {
propertyName = temp;
}
}
} else if (c2 == 'f') {
propertyName = methodName.substring(2);
} else {
propertyName = methodName.substring(2);
field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
if (field == null) {
continue;
}
}
boolean ignore = isJSONTypeIgnore(clazz, propertyName);
if (ignore) {
continue;
}
if (field == null) {
field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
}
if (field == null) {
field = ParserConfig.getFieldFromCache(methodName, fieldCacheMap);
}
JSONField fieldAnnotation = null;
if (field != null) {
fieldAnnotation = TypeUtils.getAnnotation(field, JSONField.class);
if (fieldAnnotation != null) {
if (!fieldAnnotation.serialize()) {
continue;
}
ordinal = fieldAnnotation.ordinal();
serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
if (fieldAnnotation.name().length() != 0) {
propertyName = fieldAnnotation.name();
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
}
if (fieldAnnotation.label().length() != 0) {
label = fieldAnnotation.label();
}
}
}
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
if (propertyNamingStrategy != null) {
propertyName = propertyNamingStrategy.translate(propertyName);
}
//优先选择get
if (fieldInfoMap.containsKey(propertyName)) {
continue;
}
FieldInfo fieldInfo = new FieldInfo(
propertyName,
method,
field,
clazz,
null,
ordinal,
serialzeFeatures,
parserFeatures,
annotation,
fieldAnnotation,
label
);
fieldInfoMap.put(propertyName, fieldInfo);
}
}
Field[] fields = clazz.getFields();
computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);
return getFieldInfos(clazz, sorted, fieldInfoMap);
}