Skip to content

Commit

Permalink
fix generic field type resolve error, for issue #1676
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Sep 3, 2023
1 parent c9c43a6 commit 69c02af
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,8 @@ protected void createFieldReader(

int parameterCount = method.getParameterCount();
if (parameterCount == 0) {
Type fieldType = method.getGenericReturnType();
Class<?> fieldClass = method.getReturnType();
FieldReader fieldReader = createFieldReaderMethod(
objectClass,
objectType,
Expand All @@ -1356,8 +1358,8 @@ protected void createFieldReader(
fieldInfo.locale,
fieldInfo.defaultValue,
fieldInfo.schema,
method.getGenericReturnType(),
method.getReturnType(),
fieldType,
fieldClass,
method,
fieldInfo.getInitReader()
);
Expand All @@ -1381,6 +1383,18 @@ protected void createFieldReader(

Type fieldType = method.getGenericParameterTypes()[0];
Class fieldClass = method.getParameterTypes()[0];
if (fieldType instanceof Class && Collection.class.isAssignableFrom((Class<?>) fieldType)) {
Class[] interfaces = objectClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
Method interfaceMethod = BeanUtils.getMethod(interfaces[i], method);
Type[] genericParameterTypes = interfaceMethod.getGenericParameterTypes();
if (genericParameterTypes.length == 1
&& genericParameterTypes[0] instanceof ParameterizedType
) {
fieldType = genericParameterTypes[0];
}
}
}

// skip function
if (isFunction(fieldClass)) {
Expand Down Expand Up @@ -2146,6 +2160,13 @@ public <T> FieldReader createFieldReaderMethod(
);
}

Type fieldTypeResolved = null;
Class fieldClassResolved = null;
if (!(fieldType instanceof Class) || !(objectType instanceof Class)) {
fieldTypeResolved = BeanUtils.getFieldType(TypeReference.get(objectType), objectClass, method, fieldType);
fieldClassResolved = TypeUtils.getMapping(fieldTypeResolved);
}

if (method.getParameterCount() == 0) {
if (fieldClass == AtomicInteger.class) {
return new FieldReaderAtomicIntegerMethodReadOnly(fieldName, fieldClass, ordinal, jsonSchema, method);
Expand Down Expand Up @@ -2180,7 +2201,7 @@ public <T> FieldReader createFieldReaderMethod(
}
return new FieldReaderCollectionMethodReadOnly(
fieldName,
fieldType,
fieldTypeResolved != null ? fieldTypeResolved : fieldType,
fieldClass,
ordinal,
features,
Expand Down Expand Up @@ -2216,13 +2237,6 @@ public <T> FieldReader createFieldReaderMethod(
}
}

Type fieldTypeResolved = null;
Class fieldClassResolved = null;
if (!(fieldType instanceof Class)) {
fieldTypeResolved = BeanUtils.getFieldType(TypeReference.get(objectType), objectClass, method, fieldType);
fieldClassResolved = TypeUtils.getMapping(fieldTypeResolved);
}

if (fieldClass == List.class
|| fieldClass == ArrayList.class
|| fieldClass == LinkedList.class
Expand Down
12 changes: 7 additions & 5 deletions core/src/main/java/com/alibaba/fastjson2/util/BeanUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1639,11 +1639,13 @@ public static Type getFieldType(TypeReference typeReference, Class<?> raw, Membe
return null;
}

public static Type getParamType(TypeReference type,
Class<?> raw,
Class declaringClass,
Parameter field,
Type fieldType) {
public static Type getParamType(
TypeReference type,
Class<?> raw,
Class declaringClass,
Parameter field,
Type fieldType
) {
while (raw != Object.class) {
if (declaringClass == raw) {
return resolve(type.getType(), declaringClass, fieldType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,39 @@
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.Test;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class Issue1676 {
@Test
public void test() {
public void test1() {
ParameterizedType parameterizedType = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] {Bean.class};
}

@Override
public Type getRawType() {
return PageImpl.class;
}

@Override
public Type getOwnerType() {
return null;
}
};
String s = "{\"current\":1,\"hitCount\":false,\"optimizeCountSql\":true,\"orders\":[],\"pages\":1,\"records\":[{\"name\": \"test\"}],\"searchCount\":true,\"size\":10,\"total\":1}";
PageImpl fastJson2PageObject = JSON.parseObject(s, parameterizedType);
assertEquals(Bean.class, fastJson2PageObject.getRecords().get(0).getClass());
}

@Test
public void test2() {
ParameterizedType parameterizedType = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
Expand All @@ -31,10 +55,43 @@ public Type getOwnerType() {

String s = "{\"current\":1,\"hitCount\":false,\"optimizeCountSql\":true,\"orders\":[],\"pages\":1,\"records\":[{\"name\": \"test\"}],\"searchCount\":true,\"size\":10,\"total\":1}";
Page fastJson2PageObject = JSON.parseObject(s, parameterizedType);
assertSame(Bean.class, fastJson2PageObject.getRecords().get(0).getClass());
assertEquals(Bean.class, fastJson2PageObject.getRecords().get(0).getClass());
}

public static class Bean {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

public interface IPage<T>
extends Serializable {
List<T> getRecords();

// 问题出现在这里,如果这里返回结果是IPage<T>,那么fastjson2就会解析有问题,但fastjson1不会有问题;如果返回结果是void也不会有问题
IPage<T> setRecords(List<T> records);
}

public static class PageImpl<T>
implements IPage<T> {
protected List<T> records;

@Override
public List<T> getRecords() {
return this.records;
}

@Override
public PageImpl<T> setRecords(List<T> records) {
this.records = records;
return this;
}
}

public static class Page<T> {
Expand All @@ -44,8 +101,9 @@ public List<T> getRecords() {
return records;
}

public void setRecords(List<T> records) {
public Page<T> setRecords(List<T> records) {
this.records = records;
return this;
}
}
}

0 comments on commit 69c02af

Please sign in to comment.