Browse Source

修复无法序列化List泛型问题

zhou-hao 3 years ago
parent
commit
3c8f2544e1

+ 22 - 5
hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java

@@ -32,6 +32,7 @@ import javax.annotation.Nonnull;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -120,17 +121,33 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
         }
     }
 
+    private Type getRelType(Type type) {
+        if (type instanceof Class) {
+            Class<?> realType = entityFactory.getInstanceType(((Class<?>) type), false);
+            if (realType != null) {
+                return realType;
+            }
+        }
+        return type;
+    }
+
     private ObjectReader getObjectReader(ResolvableType elementType, @Nullable Map<String, Object> hints) {
         Assert.notNull(elementType, "'elementType' must not be null");
         MethodParameter param = getParameter(elementType);
         Class<?> contextClass = (param != null ? param.getContainingClass() : null);
         Type type = elementType.resolve() == null ? elementType.getType() : elementType.toClass();
-        if (type instanceof Class) {
-            Class<?> realType = entityFactory.getInstanceType(((Class<?>) type), false);
-            if (realType != null) {
-                type = realType;
-            }
+
+        if (Iterable.class.isAssignableFrom(elementType.toClass())) {
+            ResolvableType genType = elementType.getGeneric(0);
+            type = ResolvableType
+                    .forClassWithGenerics(
+                            elementType.toClass(),
+                            ResolvableType.forType(getRelType(genType.getType())))
+                    .getType();
+        } else {
+            type = getRelType(type);
         }
+
         JavaType javaType = getJavaType(type, contextClass);
         Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
         return jsonView != null ?

+ 28 - 1
hsweb-starter/src/test/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoderTest.java

@@ -1,6 +1,8 @@
 package org.hswebframework.web.starter.jackson;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Getter;
+import lombok.Setter;
 import lombok.SneakyThrows;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
 import org.hswebframework.web.api.crud.entity.QueryParamEntity;
@@ -17,6 +19,7 @@ import org.springframework.util.MimeType;
 import reactor.core.publisher.Mono;
 
 import java.util.Collections;
+import java.util.List;
 
 import static org.junit.Assert.*;
 
@@ -28,7 +31,7 @@ public class CustomJackson2JsonDecoderTest {
 
         MapperEntityFactory entityFactory = new MapperEntityFactory();
 
-        entityFactory.addMapping(QueryParamEntity.class,MapperEntityFactory.defaultMapper(CustomQueryParamEntity.class));
+        entityFactory.addMapping(QueryParamEntity.class, MapperEntityFactory.defaultMapper(CustomQueryParamEntity.class));
 
 
         ObjectMapper mapper = new ObjectMapper();
@@ -46,6 +49,30 @@ public class CustomJackson2JsonDecoderTest {
 
     }
 
+    @Test
+    @SneakyThrows
+    public void testDecodeList() {
+        ObjectMapper mapper = new ObjectMapper();
+        CustomJackson2JsonDecoder decoder = new CustomJackson2JsonDecoder(new MapperEntityFactory(), mapper);
+
+        ResolvableType type = ResolvableType.forClassWithGenerics(List.class, MyEntity.class);
+        DataBuffer buffer = new DefaultDataBufferFactory().wrap("[{\"id\":\"test\"}]".getBytes());
+
+        Object object = decoder.decode(buffer, type, MediaType.APPLICATION_JSON, Collections.emptyMap());
+
+        assertTrue(object instanceof List);
+        assertTrue(((List<?>) object).size() > 0);
+        assertTrue(((List<?>) object).get(0) instanceof MyEntity);
+        assertEquals(((MyEntity) ((List<?>) object).get(0)).getId(), "test");
+
+    }
+
+    @Getter
+    @Setter
+    public static class MyEntity {
+        private String id;
+    }
+
     public static class CustomQueryParamEntity extends QueryParamEntity {
 
     }