diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java index ea213ec1c..8b89c554a 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java @@ -2,8 +2,10 @@ package cn.hutool.core.lang.reflect; import cn.hutool.core.convert.Convert; import cn.hutool.core.map.WeakConcurrentMap; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.TypeUtil; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -57,6 +59,22 @@ public class ActualTypeMapperPool { return result; } + public static Type getActualType(Type type, GenericArrayType genericArrayType) { + final Map<Type, Type> typeTypeMap = get(type); + Type actualType = typeTypeMap.get(genericArrayType); + + if (actualType == null) { + Type componentType = typeTypeMap.get(genericArrayType.getGenericComponentType()); + if (!(componentType instanceof Class<?>)) { + return null; + } + actualType = ArrayUtil.getArrayType((Class<?>) componentType); + typeTypeMap.put(genericArrayType, actualType); + } + + return actualType; + } + /** * 获取指定泛型变量对应的真实类型<br> * 由于子类中泛型参数实现和父类(接口)中泛型定义位置是一一对应的,因此可以通过对应关系找到泛型实现类型<br> diff --git a/hutool-core/src/main/java/cn/hutool/core/util/TypeUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/TypeUtil.java index 4ca0f7885..ab734df30 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/TypeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/TypeUtil.java @@ -3,12 +3,7 @@ package cn.hutool.core.util; import cn.hutool.core.lang.ParameterizedTypeImpl; import cn.hutool.core.lang.reflect.ActualTypeMapperPool; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; +import java.lang.reflect.*; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -412,6 +407,9 @@ public class TypeUtil { if (typeVariable instanceof TypeVariable) { return ActualTypeMapperPool.getActualType(type, (TypeVariable<?>) typeVariable); } + if (typeVariable instanceof GenericArrayType) { + return ActualTypeMapperPool.getActualType(type, (GenericArrayType) typeVariable); + } // 没有需要替换的泛型变量,原样输出 return typeVariable; diff --git a/hutool-core/src/test/java/cn/hutool/core/util/TypeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/TypeUtilTest.java index d05e46cfa..42a7e5665 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/TypeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/TypeUtilTest.java @@ -4,8 +4,12 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; + +import cn.hutool.core.lang.TypeReference; import lombok.Data; + import static org.junit.jupiter.api.Assertions.*; + import org.junit.jupiter.api.Test; public class TypeUtilTest { @@ -97,4 +101,29 @@ public class TypeUtilTest { private T level; } + + /** + * fix github:issue#3873 + */ + @Test + public void getActualTypeForGenericArrayTest() { + TypeReference<GenericArray<GenericArrayEle>> typeReference = new TypeReference<GenericArray<GenericArrayEle>>() { + + }; + + Type levelType = TypeUtil.getFieldType(GenericArray.class, "level"); + Type actualType = TypeUtil.getActualType(typeReference.getType(), levelType); + assertEquals(ArrayUtil.getArrayType(GenericArrayEle.class), actualType); + } + + @Data + public static class GenericArray<T> { + private T[] level; + } + + @Data + public static class GenericArrayEle { + private Long uid; + } + } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index fbf928000..2b5c2c04d 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -4,7 +4,9 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Console; +import cn.hutool.core.lang.TypeReference; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.json.test.bean.Price; import cn.hutool.json.test.bean.UserA; @@ -290,4 +292,27 @@ public class JSONUtilTest { final String jsonStr = JSONUtil.toJsonStr(userId); assertEquals("{}", jsonStr); } + + /** + * 类型引用数组泛型丢失 + */ + @Test + public void issue3873Test() { + String json = "{\"results\":[{\"uid\":\"1\"}],\"offset\":0,\"limit\":20,\"total\":0}"; + Results<Index> deserialize = JSONUtil.toBean(json, (new TypeReference<Results<Index>>() { + }), false); + + assertEquals(Results.class, deserialize.getClass()); + assertEquals(ArrayUtil.getArrayType(Index.class), deserialize.results.getClass()); + } + + @Data + public static class Results<T> { + public T[] results; + } + + @Data + public static class Index { + public String uid; + } }