in core/src/main/java/com/alibaba/fastjson2/reader/FieldReader.java [193:368]
public int compareTo(FieldReader o) {
int nameCompare = this.fieldName.compareTo(o.fieldName);
if (nameCompare != 0) {
if (this.ordinal < o.ordinal) {
return -1;
}
if (this.ordinal > o.ordinal) {
return 1;
}
return nameCompare;
}
int cmp = (isReadOnly() == o.isReadOnly()) ? 0 : (isReadOnly() ? 1 : -1);
if (cmp != 0) {
return cmp;
}
Member thisMember = this.field != null ? this.field : this.method;
Member otherMember = o.field != null ? o.field : o.method;
if (thisMember != null && otherMember != null && thisMember.getClass() != otherMember.getClass()) {
Class otherDeclaringClass = otherMember.getDeclaringClass();
Class thisDeclaringClass = thisMember.getDeclaringClass();
if (thisDeclaringClass != otherDeclaringClass
) {
if (thisDeclaringClass.isAssignableFrom(otherDeclaringClass)) {
return 1;
} else if (otherDeclaringClass.isAssignableFrom(thisDeclaringClass)) {
return -1;
}
}
}
if (this.field != null && o.field != null) {
Class<?> thisDeclaringClass = this.field.getDeclaringClass();
Class<?> otherDeclaringClass = o.field.getDeclaringClass();
for (Class s = thisDeclaringClass.getSuperclass(); s != null && s != Object.class; s = s.getSuperclass()) {
if (s == otherDeclaringClass) {
return 1;
}
}
for (Class s = otherDeclaringClass.getSuperclass(); s != null && s != Object.class; s = s.getSuperclass()) {
if (s == thisDeclaringClass) {
return -1;
}
}
}
if (this.method != null && o.method != null) {
Class<?> thisDeclaringClass = this.method.getDeclaringClass();
Class<?> otherDeclaringClass = o.method.getDeclaringClass();
//declaring class compare
if (thisDeclaringClass != otherDeclaringClass) {
for (Class s = thisDeclaringClass.getSuperclass(); s != null && s != Object.class; s = s.getSuperclass()) {
if (s == otherDeclaringClass) {
return -1;
}
}
for (Class s = otherDeclaringClass.getSuperclass(); s != null && s != Object.class; s = s.getSuperclass()) {
if (s == thisDeclaringClass) {
return 1;
}
}
}
if (this.method.getParameterCount() == 1 && o.method.getParameterCount() == 1) {
Class<?> thisParamType = this.method.getParameterTypes()[0];
Class<?> otherParamType = o.method.getParameterTypes()[0];
if (thisParamType != otherParamType) {
if (thisParamType.isAssignableFrom(otherParamType)) {
return 1;
}
if (otherParamType.isAssignableFrom(thisParamType)) {
return -1;
}
// Collection first
if (Collection.class.isAssignableFrom(otherParamType) && !Collection.class.isAssignableFrom(thisParamType)) {
return 1;
}
if (Collection.class.isAssignableFrom(thisParamType) && !Collection.class.isAssignableFrom(otherParamType)) {
return -1;
}
// field class compare
if (needCompareToActualFieldClass(thisParamType) || needCompareToActualFieldClass(otherParamType)) {
Class actualFieldClass = null;
try {
actualFieldClass = thisDeclaringClass.getDeclaredField(this.fieldName).getType();
if (actualFieldClass == null) {
actualFieldClass = otherDeclaringClass.getDeclaredField(this.fieldName).getType();
}
} catch (NoSuchFieldException ignored) {
// ignored
}
if (actualFieldClass != null) {
for (Class s = thisParamType; s != null && s != Object.class; s = s.getSuperclass()) {
if (s == actualFieldClass) {
return -1;
}
}
for (Class s = otherParamType; s != null && s != Object.class; s = s.getSuperclass()) {
if (s == actualFieldClass) {
return 1;
}
}
}
}
//JSONField annotation priority over non JSONField annotation
JSONField thisAnnotation = BeanUtils.findAnnotation(this.method, JSONField.class);
JSONField otherAnnotation = BeanUtils.findAnnotation(o.method, JSONField.class);
boolean thisAnnotatedWithJsonFiled = thisAnnotation != null;
if (thisAnnotatedWithJsonFiled == (otherAnnotation == null)) {
return thisAnnotatedWithJsonFiled ? -1 : 1;
}
}
}
String thisMethodName = this.method.getName();
String otherMethodName = o.method.getName();
if (!thisMethodName.equals(otherMethodName)) {
//setter priority over non setter
boolean thisMethodNameSetStart = thisMethodName.startsWith("set");
if (thisMethodNameSetStart != otherMethodName.startsWith("set")) {
return thisMethodNameSetStart ? -1 : 1;
}
//different field name priority over same field name
String thisName = BeanUtils.setterName(thisMethodName, null);
String otherName = BeanUtils.setterName(otherMethodName, null);
boolean thisFieldNameEquals = this.fieldName.equals(thisName);
if (thisFieldNameEquals != o.fieldName.equals(otherName)) {
return thisFieldNameEquals ? 1 : -1;
}
}
}
ObjectReader thisInitReader = this.getInitReader();
ObjectReader otherInitReader = o.getInitReader();
if (thisInitReader != null && otherInitReader == null) {
return -1;
}
if (thisInitReader == null && otherInitReader != null) {
return 1;
}
Class thisFieldClass = this.fieldClass;
Class otherClass = o.fieldClass;
boolean thisClassPrimitive = thisFieldClass.isPrimitive();
boolean otherClassPrimitive = otherClass.isPrimitive();
if (thisClassPrimitive && !otherClassPrimitive) {
return -1;
}
if (!thisClassPrimitive && otherClassPrimitive) {
return 1;
}
boolean thisClassStartsWithJava = thisFieldClass.getName().startsWith("java.");
boolean otherClassStartsWithJava = otherClass.getName().startsWith("java.");
if (thisClassStartsWithJava && !otherClassStartsWithJava) {
return -1;
}
if (!thisClassStartsWithJava && otherClassStartsWithJava) {
return 1;
}
return cmp;
}