浏览代码

优化泛型反序列化

zhou-hao 3 年之前
父节点
当前提交
20b25b3e94

+ 16 - 7
hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java

@@ -31,6 +31,7 @@ import reactor.core.publisher.Mono;
 import javax.annotation.Nonnull;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import java.util.List;
@@ -128,6 +129,19 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
                 return realType;
             }
         }
+        if (type instanceof ParameterizedType) {
+            ResolvableType elementType = ResolvableType.forType(type);
+            ResolvableType[] generics = elementType.getGenerics();
+            for (int i = 0; i < generics.length; i++) {
+                generics[i] = ResolvableType.forType(getRelType(generics[i].getType()));
+            }
+
+            type = ResolvableType
+                    .forClassWithGenerics(
+                            elementType.toClass(),
+                            generics)
+                    .getType();
+        }
         return type;
     }
 
@@ -137,13 +151,8 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
         Class<?> contextClass = (param != null ? param.getContainingClass() : null);
         Type type = elementType.resolve() == null ? elementType.getType() : elementType.toClass();
 
-        if (Iterable.class.isAssignableFrom(elementType.toClass())) {
-            ResolvableType genType = elementType.getGeneric(0);
-            type = ResolvableType
-                    .forClassWithGenerics(
-                            elementType.toClass(),
-                            ResolvableType.forType(getRelType(genType.getType())))
-                    .getType();
+        if (elementType.getType() instanceof ParameterizedType) {
+            type = getRelType(elementType.getType());
         } else {
             type = getRelType(type);
         }

+ 45 - 0
hsweb-starter/src/test/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoderTest.java

@@ -5,6 +5,7 @@ import lombok.Getter;
 import lombok.Setter;
 import lombok.SneakyThrows;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
+import org.hswebframework.web.api.crud.entity.PagerResult;
 import org.hswebframework.web.api.crud.entity.QueryParamEntity;
 import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
 import org.hswebframework.web.crud.web.reactive.ReactiveQueryController;
@@ -16,10 +17,15 @@ import org.springframework.core.io.buffer.DefaultDataBuffer;
 import org.springframework.core.io.buffer.DefaultDataBufferFactory;
 import org.springframework.http.MediaType;
 import org.springframework.util.MimeType;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
 import reactor.core.publisher.Mono;
 
+import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import static org.junit.Assert.*;
 
@@ -67,6 +73,45 @@ public class CustomJackson2JsonDecoderTest {
 
     }
 
+    @Test
+    @SneakyThrows
+    public void testGeneric() {
+        ObjectMapper mapper = new ObjectMapper();
+        CustomJackson2JsonDecoder decoder = new CustomJackson2JsonDecoder(new MapperEntityFactory(), mapper);
+
+        ResolvableType type = ResolvableType.forClassWithGenerics(PagerResult.class, MyEntity.class);
+        DataBuffer buffer = new DefaultDataBufferFactory().wrap("{\"pageSize\":1,\"data\":[{\"id\":\"test\"}]}".getBytes());
+
+        Object object = decoder.decode(buffer, type, MediaType.APPLICATION_JSON, Collections.emptyMap());
+
+        assertTrue(object instanceof PagerResult);
+        PagerResult<MyEntity> result= ((PagerResult<MyEntity>) object);
+
+        assertTrue(result.getData().size()>0);
+        assertEquals(result.getData().get(0).getId(), "test");
+
+    }
+
+    @Test
+    @SneakyThrows
+    public void testComplexGeneric() {
+        ObjectMapper mapper = new ObjectMapper();
+        CustomJackson2JsonDecoder decoder = new CustomJackson2JsonDecoder(new MapperEntityFactory(), mapper);
+        ResolvableType type = ResolvableType.forClassWithGenerics(PagerResult.class, ResolvableType.forClassWithGenerics(
+                Map.class,String.class,MyEntity.class
+        ));
+        DataBuffer buffer = new DefaultDataBufferFactory().wrap("{\"pageSize\":1,\"data\":[{\"test\":{\"id\":\"test\"}}]}".getBytes());
+
+        Object object = decoder.decode(buffer, type, MediaType.APPLICATION_JSON, Collections.emptyMap());
+
+        assertTrue(object instanceof PagerResult);
+        PagerResult<Map<String,MyEntity>> result= ((PagerResult<Map<String,MyEntity>>) object);
+
+        assertTrue(result.getData().size()>0);
+        assertEquals(result.getData().get(0).get("test").getId(), "test");
+    }
+
+
     @Getter
     @Setter
     public static class MyEntity {