diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java index 00635716e07..deafebd8e53 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java @@ -86,13 +86,34 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve this.prefixJson = prefixJson; } - @Override public boolean canRead(Class> clazz, MediaType mediaType) { - JavaType javaType = TypeFactory.fromClass(clazz); + JavaType javaType = getJavaType(clazz); return this.objectMapper.canDeserialize(javaType) && canRead(mediaType); } + /** + * Returns the Jackson {@link JavaType} for the specific class. + * + *
Default implementation returns {@link TypeFactory#type(java.lang.reflect.Type)}, but this can be overridden + * in subclasses, to allow for custom generic collection handling. For instance: + *
+ * protected JavaType getJavaType(Class<?> clazz) {
+ * if (List.class.isAssignableFrom(clazz)) {
+ * return TypeFactory.collectionType(ArrayList.class, MyBean.class);
+ * } else {
+ * return super.getJavaType(clazz);
+ * }
+ * }
+ *
+ *
+ * @param clazz the class to return the java type for
+ * @return the java type
+ */
+ protected JavaType getJavaType(Class> clazz) {
+ return TypeFactory.type(clazz);
+ }
+
@Override
public boolean canWrite(Class> clazz, MediaType mediaType) {
return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
@@ -107,8 +128,8 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
@Override
protected Object readInternal(Class> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
-
- return this.objectMapper.readValue(inputMessage.getBody(), clazz);
+ JavaType javaType = getJavaType(clazz);
+ return this.objectMapper.readValue(inputMessage.getBody(), javaType);
}
@Override
diff --git a/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java b/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java
index 32fb7fd3b16..a79ec58b66f 100644
--- a/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java
@@ -23,6 +23,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.codehaus.jackson.map.type.TypeFactory;
+import org.codehaus.jackson.type.JavaType;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
@@ -56,7 +58,6 @@ public class MappingJacksonHttpMessageConverterTests {
}
@Test
- @SuppressWarnings("unchecked")
public void readTyped() throws IOException {
String body =
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
@@ -71,6 +72,36 @@ public class MappingJacksonHttpMessageConverterTests {
assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
}
+ @Test
+ @SuppressWarnings("unchecked")
+ public void readGenerics() throws IOException {
+ converter = new MappingJacksonHttpMessageConverter() {
+ @Override
+ protected JavaType getJavaType(Class> clazz) {
+ if (List.class.isAssignableFrom(clazz)) {
+ return TypeFactory.collectionType(ArrayList.class, MyBean.class);
+ }
+ else {
+ return super.getJavaType(clazz);
+ }
+ }
+ };
+ String body =
+ "[{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
+ MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
+ inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
+
+ List